逆向分析CrackMe系列——CrackMe004
本次进行CrackMe003的逆向分析,前面分析的crackme难度都是一颗星,这次来试试两颗星的 ( ̄▽ ̄)*
(本系列的CrackMe资源均来自我爱破解网).
1.运行程序,发现先出现一个小的nag提示面,然后弹出主程序框:
2. 先拿PEID检查一下,用VB编写,无壳:
3. 先绕过nag窗口,第一次除nag,该过程参考大佬分析
至于为什么要除nag窗口,个人认为在用OD打开未去nag的程序时,很难找到相关的字符串或者其他的有效信息;当然也有办法:比如对相应的弹窗函数下断如rtcMsgBox。但是当去nag窗口后,直接用OD搜索就能够找到:
4. 赢OD打开程序,看到入口地址:
5. 查看入栈的地址(004067D4也就是VBHeader)中的数据:
6. VBHeader的地址加上0x4C就是指向Form GuI描述表的地址,进行查看:
7. 查看dump文件:
8. 图中的前后50H个字节分别代表两个窗口,其中标红的00和01分别是两个窗口的执行顺序,也就是nag窗口和主程序窗口;
9. 我们将它们的顺序进行交换:
10. 然后将修改的结果另存为可执行程序:
11. 我们再用OD打开修改后的程序,按照熟悉的套路查找字符串:
12. 进行跟踪:
13.观察周围的代码块,发现注册成功的字符串:
14. 仔细分析,发现是通过00408677处的跳转实现判定的,与CrackMe002比较相似,用两个 nop 进行替换:
15. 成功
16. 接下来分析注册码生成算法。
17. 从00408677处的跳转往回看,没有找到cmp,但是找到一个test si, si 用于检查 si 的值,如果为空,则修改ZF标志位,也就是说是利用si来传递注册码是否正确的信息。
18. 往前分析了部分,发现有点困难,都是浮点数操作;准备从该代码块的开始部分进行分析,先F8直到该模块的返回:
19. 然后单步F7进入刚刚分析的代码的起始地址,好家伙,从004080F0开始(刚刚分析的地方是00408674),这么长(⊙ˍ⊙)!!
20. 硬着头皮来吧!! (⊙﹏⊙) 挨个分析。(其实一开始发现要看这么长的代码,我的内心是拒绝的;不过分析分析会发现这个代码块里有很多相似的操作和代码块,基本上看了三分之一后就会发现这个现象,后面分析起来就很快了)
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. 对前面分析的代码总结,就可以得到整个注册码的生成逻辑了:
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. 总结一下:
- 与之前分析的其他相比,CrackMe003 多了一个nag窗口,另外注册码主要采用浮点运算来实现,整体思路没多大变化。
- 由于整个代码块较长,同时浮点预算较多,在刚开始分析的时候会有些烦躁,所以一定要有耐心;在分析到三分之一的时候会发现很多重复的代码,就知道哪些可以快速跳过,那哪些需要仔细注意了。