Reverse analysis of CrackMe series——CrackMe004
This time we are conducting a reverse analysis of CrackMe003. The crackme difficulty analyzed previously is all one star. This time I will try the two star one ( ̄▽ ̄) *
(The CrackMe resources in this series are all from I Love Cracking Network ).
1. Run the program and find that a small nag prompt appears first, and then the main program box pops up:
2. Check the PEID first, written in VB, without shell:
3. First bypass the nag window and remove nag for the first time. Please refer to the expert’s analysis
for this process . As for why you need to remove the nag window, I personally think that it is difficult to find relevant strings or other information when using OD to open a program that has not removed nag. Valid information; of course there are ways: for example, interrupt the corresponding pop-up window function such as rtcMsgBox. But when you go to the nag window, you can find it directly with OD search:
4. Win OD to open the program and see the entrance address:
5. View the data in the address pushed onto the stack (004067D4, which is VBHeader):
6. The address of VBHeader plus 0x4C points to the address of the Form GuI description table. Check it:
7. View the dump file:
8. The 50H bytes before and after in the figure represent two windows respectively, among which 00 and 01 marked in red are the execution order of the two windows, that is, the nag window and the main program window;
9. We swap their order:
10. Then save the modified results as an executable program:
11. We then use OD to open the modified program and search for strings according to familiar routines:
12. Follow up:
13. Observe the surrounding code blocks and find the string of successful registration:
14. After careful analysis, it is found that the judgment is achieved through the jump at 00408677, which is similar to CrackMe002. Replace it with two nops:
15. Success
16. Next, analyze the registration code generation algorithm.
17. Looking back from the jump at 00408677, no cmp is found, but a test si is found. si is used to check the value of si. If it is empty, the ZF flag is modified, which means that si is used to transfer the registration code. Is the information correct?
18. After analyzing the previous part, I found that it is a bit difficult, as they are all floating point number operations. I am going to analyze from the beginning of the code block, first F8 until the return of the module:
19. Then single-step F7 to enter the starting address of the code just analyzed. Good guy, it starts from 004080F0 (the place just analyzed is 00408674), so long (⊙ˍ⊙)! !
20. Come on bite the bullet!! (⊙﹏⊙) Analyze one by one. (Actually, when I first found out that I had to read such a long code, I refused in my heart; but after analysis, I found that there are many similar operations and code blocks in this code block. Basically, after reading a third of it, I found this Phenomenon, it will be analyzed quickly later)
004080F0 > \55 push ebp
004080F1 . 8BEC mov ebp, esp
004080F3 . 83EC 0>sub esp, 0C ; 3个局部变量
004080F6 . 68 561>push <jmp.&MSVBVM50.__vbaExceptHandler> ; SE handler installation
004080FB . 64:A1 >mov eax, dword ptr fs:[0]
00408101 . 50 push eax
00408102 . 64:892>mov dword ptr fs:[0], esp
00408109 . 81EC D>sub esp, 0D0
0040810F . 53 push ebx
00408110 . 56 push esi ; 寄存器保护
00408111 . 8B75 0>mov esi, dword ptr [ebp+8] ; esi=[002A0C29]=0000409A
00408114 . 57 push edi
00408115 . 8BC6 mov eax, esi ; eax=esi=0000409A
00408117 . 83E6 F>and esi, FFFFFFFE ; esi=002A0C28 改变了最后一位
0040811A . 8965 F>mov dword ptr [ebp-C], esp
0040811D . 83E0 0>and eax, 1 ; eax=1
00408120 . 8B1E mov ebx, dword ptr [esi]
00408122 . C745 F>mov dword ptr [ebp-8], 00401030
00408129 . 56 push esi
0040812A . 8945 F>mov dword ptr [ebp-4], eax
0040812D . 8975 0>mov dword ptr [ebp+8], esi
00408130 . 899D 4>mov dword ptr [ebp-C0], ebx
00408136 . FF53 0>call dword ptr [ebx+4] ; MSVBVMS0.BASIC_CLASS_AddRef
00408139 . 8B83 0>mov eax, dword ptr [ebx+308] ; 库函数
0040813F . 33FF xor edi, edi ; edi清零
00408141 . 56 push esi
00408142 . 897D E>mov dword ptr [ebp-18], edi
00408145 . 897D E>mov dword ptr [ebp-1C], edi
00408148 . 897D E>mov dword ptr [ebp-20], edi
0040814B . 897D D>mov dword ptr [ebp-24], edi
0040814E . 897D D>mov dword ptr [ebp-28], edi
00408151 . 897D D>mov dword ptr [ebp-2C], edi
00408154 . 897D C>mov dword ptr [ebp-3C], edi
00408157 . 897D B>mov dword ptr [ebp-4C], edi
0040815A . 897D A>mov dword ptr [ebp-5C], edi
0040815D . 897D 9>mov dword ptr [ebp-6C], edi ; 全部清零
00408160 . FFD0 call eax ; MSVBVMS0.0F10C358
00408162 . 8D4D D>lea ecx, dword ptr [ebp-2C]
00408165 . 50 push eax
00408166 . 51 push ecx
00408167 . FF15 2>call dword ptr [<&MSVBVM50.__vbaObjSet>] ; MSVBVM50.__vbaObjSet
0040816D . 8B9B 1>mov ebx, dword ptr [ebx+318]
00408173 . 56 push esi
00408174 . 8985 5>mov dword ptr [ebp-B0], eax
0040817A . 899D 3>mov dword ptr [ebp-C4], ebx
00408180 . FFD3 call ebx
00408182 . 8D55 D>lea edx, dword ptr [ebp-24]
00408185 . 50 push eax
00408186 . 52 push edx
00408187 . FF15 2>call dword ptr [<&MSVBVM50.__vbaObjSet>] ; MSVBVM50.__vbaObjSet
0040818D . 8BD8 mov ebx, eax
0040818F . 8D4D E>lea ecx, dword ptr [ebp-18] ; [ebp-18]初始值为0x0000000
00408192 . 51 push ecx
00408193 . 53 push ebx
00408194 . 8B03 mov eax, dword ptr [ebx]
00408196 . FF90 A>call dword ptr [eax+A0] ; [ebp-18]存放了输入的用户名‘11111’
0040819C . 3BC7 cmp eax, edi
0040819E . 7D 12 jge short 004081B2 ; 如果eax>=edi 此处二者均为0
004081A0 . 68 A00>push 0A0
004081A5 . 68 AC6>push 00406FAC
004081AA . 53 push ebx
004081AB . 50 push eax
004081AC . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
004081B2 > 56 push esi
004081B3 . FF95 3>call dword ptr [ebp-C4]
004081B9 . 8D55 D>lea edx, dword ptr [ebp-28] ; [ebp-28]初始值为0x00000000
004081BC . 50 push eax
004081BD . 52 push edx
004081BE . FF15 2>call dword ptr [<&MSVBVM50.__vbaObjSet>] ; MSVBVM50_vbaObjSet 修改[ebp-28]=01B6B364
004081C4 . 8BD8 mov ebx, eax ; ebx=eax=01B6B364
004081C6 . 8D4D E>lea ecx, dword ptr [ebp-1C] ; [ebp-1C]初始值为0x00000000
004081C9 . 51 push ecx
004081CA . 53 push ebx
004081CB . 8B03 mov eax, dword ptr [ebx] ; eax=[ebx]=01B634E0
004081CD . FF90 A>call dword ptr [eax+A0] ; [ebp-1C]变为输入的用户名"11111"
004081D3 . 3BC7 cmp eax, edi ; edi=0
004081D5 . 7D 12 jge short 004081E9
004081D7 . 68 A00>push 0A0
004081DC . 68 AC6>push 00406FAC
004081E1 . 53 push ebx
004081E2 . 50 push eax
004081E3 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
004081E9 > 8B95 5>mov edx, dword ptr [ebp-B0] ; edx=[ebp-B0]=01B6ADC4
004081EF . 8B45 E>mov eax, dword ptr [ebp-1C] ; eax=[ebp-1C]='11111'
004081F2 . 50 push eax ; /String
004081F3 . 8B1A mov ebx, dword ptr [edx] ; |该函数计算用户名的长度
004081F5 . FF15 F>call dword ptr [<&MSVBVM50.__vbaLenBstr>] ; \__vbaLenBstr
004081FB . 8BF8 mov edi, eax ; edi=eax=用户名的长度=5
004081FD . 8B4D E>mov ecx, dword ptr [ebp-18] ; ecx=[ebp-18]='11111'
00408200 . 69FF 3>imul edi, edi, 15B38 ; edi=edi*0x15B38=0x0006C818
00408206 . 51 push ecx ; /String
00408207 . 0F80 B>jo 004087C4 ; |该函数计算字符串首字符的ASCII,存放在eax中
0040820D . FF15 0>call dword ptr [<&MSVBVM50.#516>] ; \rtcAnsiValueBstr
00408213 . 0FBFD0 movsx edx, ax ; edx=ax=0x31, 用户名的首字符ASCII
00408216 . 03FA add edi, edx ; edi=edi+edx=0x0006C818+0x31=0006C849
00408218 . 0F80 A>jo 004087C4 ; 溢出检查
0040821E . 57 push edi ; 下面的函数是16进制转10进制
0040821F . FF15 F>call dword ptr [<&MSVBVM50.__vbaStrI4>] ; MSVBVM50.__vbaStrI4
00408225 . 8BD0 mov edx, eax ; edx=eax='444489'
00408227 . 8D4D E>lea ecx, dword ptr [ebp-20] ; ecx指向[ebp-20],初始值为0
0040822A . FF15 9>call dword ptr [<&MSVBVM50.__vbaStrMove>] ; MSVBVM50_vbaStrMove [ebp-20]存放"444489"
00408230 . 8BBD 5>mov edi, dword ptr [ebp-B0] ; edi指向[ebp-B0] 初始值为0x00000000
00408236 . 50 push eax ; eax="444489"入栈
00408237 . 57 push edi ; ebp-B0地址入栈
00408238 . FF93 A>call dword ptr [ebx+A4] ; 返回值 eax=0; [ebp-B0]存放一个函数的地址
0040823E . 85C0 test eax, eax ; 检查eax是否为0
00408240 . 7D 12 jge short 00408254
00408242 . 68 A40>push 0A4
00408247 . 68 AC6>push 00406FAC
0040824C . 57 push edi
0040824D . 50 push eax
0040824E . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
00408254 > 8D45 E>lea eax, dword ptr [ebp-20] ; eax=[0018F418]="444489"
00408257 . 8D4D E>lea ecx, dword ptr [ebp-1C] ; ecx=[0018F41C]=用户名"11111"
0040825A . 50 push eax
0040825B . 8D55 E>lea edx, dword ptr [ebp-18] ; edx=[0018F420]=用户名"11111"
0040825E . 51 push ecx
0040825F . 52 push edx
00408260 . 6A 03 push 3 ; 3入栈;下面函数释放这三个字符串,内存地址内容清零
00408262 . FF15 8>call dword ptr [<&MSVBVM50.__vbaFreeStrLi>; MSVBVM50.__vbaFreeStrList
00408268 . 83C4 1>add esp, 10 ; 4个变量
0040826B . 8D45 D>lea eax, dword ptr [ebp-2C] ; eax=01B6ADC4
0040826E . 8D4D D>lea ecx, dword ptr [ebp-28] ; ecx=01B6B364
00408271 . 8D55 D>lea edx, dword ptr [ebp-24] ; edx=01B6B364
00408274 . 50 push eax
00408275 . 51 push ecx
00408276 . 52 push edx
00408277 . 6A 03 push 3 ; 释放三个对象
00408279 . FF15 0>call dword ptr [<&MSVBVM50.__vbaFreeObjLi>; MSVBVM50.__vbaFreeObjList
0040827F . 8B9D 4>mov ebx, dword ptr [ebp-C0]
00408285 . 83C4 1>add esp, 10 ; 4个变量
00408288 . 8B83 F>mov eax, dword ptr [ebx+2FC]
0040828E . 56 push esi
0040828F . 8985 3>mov dword ptr [ebp-C8], eax
00408295 . FFD0 call eax
00408297 . 8B3D 2>mov edi, dword ptr [<&MSVBVM50.__vbaObjS>; MSVBVM50.__vbaObjSet
0040829D . 50 push eax
0040829E . 8D45 D>lea eax, dword ptr [ebp-28] ; eax指向[ebp-28] 初始值为0
004082A1 . 50 push eax
004082A2 . FFD7 call edi ; <&MSVBVM50.__vbaObjSet>
004082A4 . 56 push esi
004082A5 . 8985 5>mov dword ptr [ebp-A8], eax
004082AB . FF93 0>call dword ptr [ebx+308]
004082B1 . 8D4D D>lea ecx, dword ptr [ebp-24] ; ecx指向[ebp-24]初始值为0
004082B4 . 50 push eax
004082B5 . 51 push ecx
004082B6 . FFD7 call edi
004082B8 . 8BD8 mov ebx, eax
004082BA . 8D45 E>lea eax, dword ptr [ebp-18] ; eax指向[ebp-18]初始值为0
004082BD . 50 push eax
004082BE . 53 push ebx
004082BF . 8B13 mov edx, dword ptr [ebx]
004082C1 . FF92 A>call dword ptr [edx+A0] ; [ebp-18]存放刚刚计算得到的"444489", 返回值eax=0
004082C7 . 85C0 test eax, eax
004082C9 . 7D 12 jge short 004082DD
004082CB . 68 A00>push 0A0
004082D0 . 68 AC6>push 00406FAC
004082D5 . 53 push ebx
004082D6 . 50 push eax
004082D7 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
004082DD > 8B8D 5>mov ecx, dword ptr [ebp-A8]
004082E3 . 8B55 E>mov edx, dword ptr [ebp-18] ; "444489"
004082E6 . 52 push edx
004082E7 . 8B19 mov ebx, dword ptr [ecx] ; 下面函数将字符串转换成浮点数放在ST0
004082E9 . FF15 7>call dword ptr [<&MSVBVM50.__vbaR8Str>] ; MSVBVM50._vbaR8Str 将一个字符串转为双精度单精度浮点型(8个字节)的数值形式
004082EF . D905 0>fld dword ptr [401008] ; 内存数据入栈(ST*中)值为10
004082F5 . 833D 0>cmp dword ptr [409000], 0 ; 内存的值为0
004082FC . 75 08 jnz short 00408306
004082FE . D835 0>fdiv dword ptr [40100C] ; STO=STO/[40100C]=2 浮点运算, [40100C]=5.00
00408304 . EB 0B jmp short 00408311
00408306 > FF35 0>push dword ptr [40100C] ; 浮点数5.00进栈
0040830C . E8 578>call <jmp.&MSVBVM50._adj_fdiv_m32>
00408311 > 83EC 0>sub esp, 8 ; 新增两个变量
00408314 . DFE0 fstsw ax ; ax=0x3000
00408316 . A8 0D test al, 0D ; al and 0x0D
00408318 . 0F85 A>jnz 004087BF
0040831E . DEC1 faddp st(1), st ; st1=st1+st0=444491.00;然后将st0出栈(到st7)
00408320 . DFE0 fstsw ax ; ax=0x3800
00408322 . A8 0D test al, 0D ; al and 0x0D
00408324 . 0F85 9>jnz 004087BF
0040832A . DD1C24 fstp qword ptr [esp] ; 4个字节[0018F340]=ST0=444491.00;然后st0出栈
0040832D . FF15 4>call dword ptr [<&MSVBVM50.__vbaStrR8>] ; MSVBVM50.__vbaStrR8
00408333 . 8BD0 mov edx, eax ; float转ASCII; edx= eax="444491"
00408335 . 8D4D E>lea ecx, dword ptr [ebp-1C] ; ex指向[ebp-1C] 初始值为0
00408338 . FF15 9>call dword ptr [<&MSVBVM50.__vbaStrMove>] ; MSVBVM50._vbaStrMove; [ebp-1C] 存放"444491"
0040833E . 899D 3>mov dword ptr [ebp-CC], ebx
00408344 . 8B9D 5>mov ebx, dword ptr [ebp-A8]
0040834A . 50 push eax ; ASCII "444491"入栈
0040834B . 8B85 3>mov eax, dword ptr [ebp-CC]
00408351 . 53 push ebx
00408352 . FF90 A>call dword ptr [eax+A4] ; 返回值eax=0
00408358 . 85C0 test eax, eax ; 检查eax是否为0
0040835A . 7D 12 jge short 0040836E
0040835C . 68 A40>push 0A4
00408361 . 68 AC6>push 00406FAC
00408366 . 53 push ebx
00408367 . 50 push eax
00408368 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
0040836E > 8D4D E>lea ecx, dword ptr [ebp-1C] ; ecx指向[rbp-1C]="444491"
00408371 . 8D55 E>lea edx, dword ptr [ebp-18] ; edx指向[ebp-18]="444489"
00408374 . 51 push ecx
00408375 . 52 push edx
00408376 . 6A 02 push 2 ; 释放两个对象
00408378 . FF15 8>call dword ptr [<&MSVBVM50.__vbaFreeStrLi>; MSVBVM50.__vbaFreeStrList
0040837E . 83C4 0>add esp, 0C
00408381 . 8D45 D>lea eax, dword ptr [ebp-28]
00408384 . 8D4D D>lea ecx, dword ptr [ebp-24]
00408387 . 50 push eax
00408388 . 51 push ecx
00408389 . 6A 02 push 2
0040838B . FF15 0>call dword ptr [<&MSVBVM50.__vbaFreeObjLi>; MSVBVM50.__vbaFreeObjList
00408391 . 8B95 4>mov edx, dword ptr [ebp-C0]
00408397 . 83C4 0>add esp, 0C
0040839A . 8B82 0>mov eax, dword ptr [edx+300]
004083A0 . 56 push esi
004083A1 . 8985 3>mov dword ptr [ebp-D0], eax
004083A7 . FFD0 call eax
004083A9 . 50 push eax
004083AA . 8D45 D>lea eax, dword ptr [ebp-28]
004083AD . 50 push eax
004083AE . FFD7 call edi
004083B0 . 56 push esi
004083B1 . 8985 5>mov dword ptr [ebp-A8], eax
004083B7 . FF95 3>call dword ptr [ebp-C8]
004083BD . 8D4D D>lea ecx, dword ptr [ebp-24]
004083C0 . 50 push eax
004083C1 . 51 push ecx
004083C2 . FFD7 call edi
004083C4 . 8BD8 mov ebx, eax
004083C6 . 8D45 E>lea eax, dword ptr [ebp-18] ; eax指向[ebp-18]
004083C9 . 50 push eax
004083CA . 53 push ebx
004083CB . 8B13 mov edx, dword ptr [ebx] ; [ebp-18]="444491"
004083CD . FF92 A>call dword ptr [edx+A0] ; MSVBVM50._0F05A5B6
004083D3 . 85C0 test eax, eax ; eax=0
004083D5 . 7D 12 jge short 004083E9
004083D7 . 68 A00>push 0A0
004083DC . 68 AC6>push 00406FAC
004083E1 . 53 push ebx
004083E2 . 50 push eax
004083E3 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
004083E9 > 8B8D 5>mov ecx, dword ptr [ebp-A8]
004083EF . 8B55 E>mov edx, dword ptr [ebp-18] ; "444491"
004083F2 . 52 push edx
004083F3 . 8B19 mov ebx, dword ptr [ecx]
004083F5 . FF15 7>call dword ptr [<&MSVBVM50.__vbaR8Str>] ; ASCII转浮点数,保存到ST0
004083FB . DC0D 1>fmul qword ptr [401010] ; ST0=ST0*[401010]=444491*3=1333473.00 内存浮点数为3
00408401 . 83EC 0>sub esp, 8
00408404 . DC25 1>fsub qword ptr [401018] ; ST0=ST0-2.00=1333471.00 内存浮点数为2
0040840A . DFE0 fstsw ax ; ax=0x3800
0040840C . A8 0D test al, 0D
0040840E . 0F85 A>jnz 004087BF
00408414 . DD1C24 fstp qword ptr [esp] ; [0018F340]=st0, st0再出栈,到st7
00408417 . FF15 4>call dword ptr [<&MSVBVM50.__vbaStrR8>] ; MSVBVM50.__vbaStrR8
0040841D . 8BD0 mov edx, eax ; edx=eax="1333471"
0040841F . 8D4D E>lea ecx, dword ptr [ebp-1C] ; [ebp-1C]被下面函数赋值为"1333471"
00408422 . FF15 9>call dword ptr [<&MSVBVM50.__vbaStrMove>] ; MSVBVM50.__vbaStrMove
00408428 . 899D 2>mov dword ptr [ebp-D4], ebx
0040842E . 8B9D 5>mov ebx, dword ptr [ebp-A8]
00408434 . 50 push eax
00408435 . 8B85 2>mov eax, dword ptr [ebp-D4]
0040843B . 53 push ebx
0040843C . FF90 A>call dword ptr [eax+A4] ; 返回值eax=0
00408442 . 85C0 test eax, eax
00408444 . 7D 12 jge short 00408458
00408446 . 68 A40>push 0A4
0040844B . 68 AC6>push 00406FAC
00408450 . 53 push ebx
00408451 . 50 push eax
00408452 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
00408458 > 8D4D E>lea ecx, dword ptr [ebp-1C]
0040845B . 8D55 E>lea edx, dword ptr [ebp-18]
0040845E . 51 push ecx
0040845F . 52 push edx
00408460 . 6A 02 push 2 ; 再次释放
00408462 . FF15 8>call dword ptr [<&MSVBVM50.__vbaFreeStrLi>; MSVBVM50.__vbaFreeStrList
00408468 . 83C4 0>add esp, 0C
0040846B . 8D45 D>lea eax, dword ptr [ebp-28]
0040846E . 8D4D D>lea ecx, dword ptr [ebp-24]
00408471 . 50 push eax
00408472 . 51 push ecx
00408473 . 6A 02 push 2 ; 释放对象
00408475 . FF15 0>call dword ptr [<&MSVBVM50.__vbaFreeObjLi>; MSVBVM50.__vbaFreeObjList
0040847B . 8B95 4>mov edx, dword ptr [ebp-C0]
00408481 . 83C4 0>add esp, 0C
00408484 . 8B82 0>mov eax, dword ptr [edx+304]
0040848A . 56 push esi
0040848B . 8985 2>mov dword ptr [ebp-D8], eax
00408491 . FFD0 call eax
00408493 . 50 push eax
00408494 . 8D45 D>lea eax, dword ptr [ebp-28]
00408497 . 50 push eax
00408498 . FFD7 call edi
0040849A . 56 push esi
0040849B . 8985 5>mov dword ptr [ebp-A8], eax
004084A1 . FF95 3>call dword ptr [ebp-D0]
004084A7 . 8D4D D>lea ecx, dword ptr [ebp-24]
004084AA . 50 push eax
004084AB . 51 push ecx
004084AC . FFD7 call edi
004084AE . 8BD8 mov ebx, eax
004084B0 . 8D45 E>lea eax, dword ptr [ebp-18] ; eax指向ebp-18
004084B3 . 50 push eax
004084B4 . 53 push ebx
004084B5 . 8B13 mov edx, dword ptr [ebx]
004084B7 . FF92 A>call dword ptr [edx+A0]
004084BD . 85C0 test eax, eax
004084BF . 7D 12 jge short 004084D3
004084C1 . 68 A00>push 0A0
004084C6 . 68 AC6>push 00406FAC
004084CB . 53 push ebx
004084CC . 50 push eax
004084CD . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
004084D3 > 8B8D 5>mov ecx, dword ptr [ebp-A8]
004084D9 . 8B55 E>mov edx, dword ptr [ebp-18] ; edx=[ebp-18]="1333471"
004084DC . 52 push edx
004084DD . 8B19 mov ebx, dword ptr [ecx]
004084DF . FF15 7>call dword ptr [<&MSVBVM50.__vbaR8Str>] ; 字符串转浮点数
004084E5 . DC25 2>fsub qword ptr [401020] ; st0=st0-(-15)=1333486.00
004084EB . 83EC 0>sub esp, 8
004084EE . DFE0 fstsw ax ; ax=0x3800
004084F0 . A8 0D test al, 0D
004084F2 . 0F85 C>jnz 004087BF
004084F8 . DD1C24 fstp qword ptr [esp] ; [0018F340]=st0=1333486.00; st0再弹栈
004084FB . FF15 4>call dword ptr [<&MSVBVM50.__vbaStrR8>] ; 浮点数转字符串
00408501 . 8BD0 mov edx, eax ; edx=eax="1333486"
00408503 . 8D4D E>lea ecx, dword ptr [ebp-1C] ; [ebp-1C]存"1333486"
00408506 . FF15 9>call dword ptr [<&MSVBVM50.__vbaStrMove>] ; MSVBVM50.__vbaStrMove
0040850C . 899D 2>mov dword ptr [ebp-DC], ebx
00408512 . 8B9D 5>mov ebx, dword ptr [ebp-A8]
00408518 . 50 push eax
00408519 . 8B85 2>mov eax, dword ptr [ebp-DC]
0040851F . 53 push ebx
00408520 . FF90 A>call dword ptr [eax+A4] ; 返回值eax=0
00408526 . 85C0 test eax, eax
00408528 . 7D 12 jge short 0040853C
0040852A . 68 A40>push 0A4
0040852F . 68 AC6>push 00406FAC
00408534 . 53 push ebx
00408535 . 50 push eax
00408536 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
0040853C > 8D4D E>lea ecx, dword ptr [ebp-1C]
0040853F . 8D55 E>lea edx, dword ptr [ebp-18]
00408542 . 51 push ecx
00408543 . 52 push edx
00408544 . 6A 02 push 2 ; 释放空间
00408546 . FF15 8>call dword ptr [<&MSVBVM50.__vbaFreeStrLi>; MSVBVM50.__vbaFreeStrList
0040854C . 83C4 0>add esp, 0C
0040854F . 8D45 D>lea eax, dword ptr [ebp-28]
00408552 . 8D4D D>lea ecx, dword ptr [ebp-24]
00408555 . 50 push eax
00408556 . 51 push ecx
00408557 . 6A 02 push 2 ; 释放对象
00408559 . FF15 0>call dword ptr [<&MSVBVM50.__vbaFreeObjLi>; MSVBVM50.__vbaFreeObjList
0040855F . 83C4 0>add esp, 0C
00408562 . 56 push esi
00408563 . FF95 2>call dword ptr [ebp-D8]
00408569 . 8D55 D>lea edx, dword ptr [ebp-28]
0040856C . 50 push eax
0040856D . 52 push edx
0040856E . FFD7 call edi
00408570 . 8BD8 mov ebx, eax
00408572 . 8D4D E>lea ecx, dword ptr [ebp-1C] ; ecx指向[ebp-1C]初始值为0
00408575 . 51 push ecx
00408576 . 53 push ebx
00408577 . 8B03 mov eax, dword ptr [ebx]
00408579 . FF90 A>call dword ptr [eax+A0] ; MSVBVM50._0F05A5B6
0040857F . 85C0 test eax, eax
00408581 . 7D 12 jge short 00408595
00408583 . 68 A00>push 0A0
00408588 . 68 AC6>push 00406FAC
0040858D . 53 push ebx
0040858E . 50 push eax
0040858F . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
00408595 > 8B95 4>mov edx, dword ptr [ebp-C0]
0040859B . 56 push esi
0040859C . FF92 1>call dword ptr [edx+314]
004085A2 . 50 push eax
004085A3 . 8D45 D>lea eax, dword ptr [ebp-24] ; eax指向[ebp-24]初始值为0
004085A6 . 50 push eax
004085A7 . FFD7 call edi ; 初始化对象
004085A9 . 8BF0 mov esi, eax
004085AB . 8D55 E>lea edx, dword ptr [ebp-18] ; edx指向[ebp-18]初始值为0
004085AE . 52 push edx
004085AF . 56 push esi
004085B0 . 8B0E mov ecx, dword ptr [esi]
004085B2 . FF91 A>call dword ptr [ecx+A0] ; MSVBVM50._0F05A5B6
004085B8 . 85C0 test eax, eax ; 获取输入的注册码存放在[ebp-18]中
004085BA . 7D 12 jge short 004085CE
004085BC . 68 A00>push 0A0
004085C1 . 68 AC6>push 00406FAC
004085C6 . 56 push esi
004085C7 . 50 push eax
004085C8 . FF15 1>call dword ptr [<&MSVBVM50.__vbaHresultCh>; MSVBVM50.__vbaHresultCheckObj
004085CE > 8B45 E>mov eax, dword ptr [ebp-18] ; eax指向[ebp-18],为输入的注册码"222222"
004085D1 . 50 push eax
004085D2 . FF15 7>call dword ptr [<&MSVBVM50.__vbaR8Str>] ; 字符串转换成浮点数存放在st0中
004085D8 . 8B4D E>mov ecx, dword ptr [ebp-1C] ; ecx=[ebp-1C]="1333486"
004085DB . DD9D 1>fstp qword ptr [ebp-E4] ; [ebp-E4]=st0=222222.00 然后st0弹栈到st7
004085E1 . 51 push ecx ; ecx="1333486"
004085E2 . FF15 7>call dword ptr [<&MSVBVM50.__vbaR8Str>] ; 字符串转换成浮点数存放在st0中
004085E8 . 833D 0>cmp dword ptr [409000], 0 ; 内存值为0
004085EF . 75 08 jnz short 004085F9
004085F1 . DCBD 1>fdivr qword ptr [ebp-E4] ; [ebp-E4]的值也就是输入的注册码浮点数, 除以ST(0), 结果存放到ST(0)=0.1666474
004085F7 . EB 11 jmp short 0040860A
004085F9 > FFB5 2>push dword ptr [ebp-E0]
004085FF . FFB5 1>push dword ptr [ebp-E4]
00408605 . E8 888>call <jmp.&MSVBVM50._adj_fdivr_m64>
0040860A > DFE0 fstsw ax ; ax=0x3820
0040860C . A8 0D test al, 0D
0040860E . 0F85 A>jnz 004087BF
00408614 . FF15 3>call dword ptr [<&MSVBVM50.__vbaFpR8>] ; st7计算得1.000;eax=0x3A20
0040861A . DC1D 2>fcomp qword ptr [401028] ; ST0与内存内容比较,内存值为1.0000;st0再弹栈到st7 (实际上就是比较输入的注册码和正确的注册码是否一致)
00408620 . DFE0 fstsw ax ; 状态字到ax=0x120
00408622 . F6C4 4>test ah, 40 ; ah=0x01与0x40相与(and)结果为0
00408625 . 74 07 je short 0040862E
00408627 . BE 010>mov esi, 1 ; 如果test结果不为0,则esi=1
0040862C . EB 02 jmp short 00408630
0040862E > 33F6 xor esi, esi ; esi 清零
00408630 > 8D55 E>lea edx, dword ptr [ebp-1C] ; edx 指向 [ebp-1C]
00408633 . 8D45 E>lea eax, dword ptr [ebp-18] ; eax 指向[ebp-18]
00408636 . 52 push edx
00408637 . 50 push eax
00408638 . 6A 02 push 2
0040863A . FF15 8>call dword ptr [<&MSVBVM50.__vbaFreeStrLi>; MSVBVM50.__vbaFreeStrList
00408640 . 83C4 0>add esp, 0C
00408643 . 8D4D D>lea ecx, dword ptr [ebp-28]
00408646 . 8D55 D>lea edx, dword ptr [ebp-24]
00408649 . 51 push ecx
0040864A . 52 push edx
0040864B . 6A 02 push 2
0040864D . FF15 0>call dword ptr [<&MSVBVM50.__vbaFreeObjLi>; MSVBVM50.__vbaFreeObjList
00408653 . F7DE neg esi ; 对esi 求反
00408655 . 83C4 0>add esp, 0C
00408658 . B9 040>mov ecx, 80020004
0040865D . B8 0A0>mov eax, 0A
00408662 . 894D 9>mov dword ptr [ebp-64], ecx
00408665 . 66:85F>test si, si ; 检查esi 是否为0,同时修改ZF标志位
00408668 . 8945 9>mov dword ptr [ebp-6C], eax
0040866B . 894D A>mov dword ptr [ebp-54], ecx
0040866E . 8945 A>mov dword ptr [ebp-5C], eax
00408671 . 894D B>mov dword ptr [ebp-44], ecx
00408674 . 8945 B>mov dword ptr [ebp-4C], eax
00408677 . 74 62 je short 004086DB ; je short 004086DB
00408679 . 8B35 1>mov esi, dword ptr [<&MSVBVM50.__vbaStrC>; MSVBVM50.__vbaStrCat
0040867F . 68 C06>push 00406FC0 ; UNICODE "You Get It"
00408684 . 68 DC6>push 00406FDC ; /String = CR,""
00408689 . FFD6 call esi ; \__vbaStrCat
0040868B . 8BD0 mov edx, eax
0040868D . 8D4D E>lea ecx, dword ptr [ebp-18]
00408690 . FF15 9>call dword ptr [<&MSVBVM50.__vbaStrMove>] ; MSVBVM50.__vbaStrMove
00408696 . 50 push eax
00408697 . 68 E86>push 00406FE8 ; UNICODE "KeyGen It Now"
0040869C . FFD6 call esi
0040869E . 8945 C>mov dword ptr [ebp-34], eax
004086A1 . 8D45 9>lea eax, dword ptr [ebp-6C]
004086A4 . 8D4D A>lea ecx, dword ptr [ebp-5C]
004086A7 . 50 push eax
004086A8 . 8D55 B>lea edx, dword ptr [ebp-4C]
004086AB . 51 push ecx
004086AC . 52 push edx
004086AD . 8D45 C>lea eax, dword ptr [ebp-3C]
004086B0 . 6A 00 push 0
004086B2 . 50 push eax
004086B3 . C745 C>mov dword ptr [ebp-3C], 8
004086BA . FF15 2>call dword ptr [<&MSVBVM50.#595>] ; MSVBVM50.rtcMsgBox
004086C0 . 8D4D E>lea ecx, dword ptr [ebp-18]
004086C3 . FF15 A>call dword ptr [<&MSVBVM50.__vbaFreeStr>] ; MSVBVM50.__vbaFreeStr
004086C9 . 8D4D 9>lea ecx, dword ptr [ebp-6C]
004086CC . 8D55 A>lea edx, dword ptr [ebp-5C]
004086CF . 51 push ecx
004086D0 . 8D45 B>lea eax, dword ptr [ebp-4C]
004086D3 . 52 push edx
004086D4 . 8D4D C>lea ecx, dword ptr [ebp-3C]
004086D7 . 50 push eax
004086D8 . 51 push ecx
004086D9 . EB 60 jmp short 0040873B
004086DB > 8B35 1>mov esi, dword ptr [<&MSVBVM50.__vbaStrC>; MSVBVM50.__vbaStrCat
004086E1 . 68 087>push 00407008 ; UNICODE "You Get Wrong"
004086E6 . 68 DC6>push 00406FDC ; /String = CR,""
004086EB . FFD6 call esi ; \__vbaStrCat
004086ED . 8BD0 mov edx, eax
004086EF . 8D4D E>lea ecx, dword ptr [ebp-18]
004086F2 . FF15 9>call dword ptr [<&MSVBVM50.__vbaStrMove>] ; MSVBVM50.__vbaStrMove
004086F8 . 50 push eax
004086F9 . 68 287>push 00407028 ; UNICODE "Try Again"
21. Summarizing the previously analyzed code, you can get the entire registration code generation logic:
1) 获取输入的用户名name ; “11111”
2) 计算用户名的长度length ; length=5
3) 获取用户名首字符的ASCII Fname ; Fname=0x31
4) 计算F1=0x00015B38 25×length ; F1=0x15B38×5=0x6C818
5) 计算F2=F1+Fname ; F2=0x6C818+0x31=0x6C849
6) F2进行十六进制转十进制得到字符串 ”f2” ; “f2”=” f2=444489”
7) “ f2 “ 转换为浮点数得到f2 ; f2=444489.00
8) 浮点计算 f3=f2+2 ; f3=444491
9) 浮点计算 f4=f3×3 -2 ; f4=444491×3-2=1333471.00
10)浮点计算 f5=f4+15 ; f5=1333471+15=1333486.00
11)注册码 = f5转字符串 ; 注册码= "1333486"
22. To summarize:
- Compared with others analyzed before, CrackMe003 has an additional nag window. In addition, the registration code is mainly implemented using floating point operations. The overall idea has not changed much.
- Since the entire code block is long and the floating point budget is large, you will be a little irritable at the beginning of the analysis, so you must be patient; when you get to one-third of the analysis, you will find a lot of repeated code, and you will know which ones can be Quickly skip to those that require careful attention.