前言
160个CrackMe的第四个。
准备
系统:Windows 7 SP1 x64 ultimate
工具:吾爱破解专用OllyDbg
分析
运行程序。
根据程序作者所说,该程序Delphi所写,有趣的是没有注册按钮,也看不到任何错误提示。但是如果注册码正确,会弹出朱茵小姐姐的照片,而且当鼠标放在灰框框里时,会给出一个提示,还有程序标题。
没什么信息,载入OD搜索下字符串,却意外发现了恭喜恭喜!注册成功
的字符串,那就这样就可以找到成功弹窗的函数了。
双击字符串进入汇编窗口,向上找到跳转位置。
00458031 |. 81BE 0C030000>cmp dword ptr ds:[esi+0x30C],0x85
0045803B |. 75 76 jnz short CKme.004580B3
...
00458096 |. 8B86 F0020000 mov eax,dword ptr ds:[esi+0x2F0]
0045809C |. E8 BFB1FCFF call CKme.00423260
004580A1 |. A1 20B84500 mov eax,dword ptr ds:[0x45B820]
004580A6 |. 83C0 70 add eax,0x70
004580A9 |. BA 14814500 mov edx,CKme.00458114 ; 恭喜恭喜!注册成功
004580AE |. E8 9DB8FAFF call CKme.00403950
004580B3 |> 33C0 xor eax,eax ; kernel32.BaseThreadInitThunk
而成功的条件则是esi+0x30C中的值等于0x85,搜索程序中常量0x85,发现只有一处是将0x85赋给esi+0x30C,我们在这两处函数头下断,却发现左击灰框框可以断在成功弹窗的函数,而不论怎么操作都无法断在第二处函数0x00457E7C。
因为Delphi这些函数是由事件驱动的,所以我们可以猜测含有成功弹窗的函数可能是鼠标左击事件函数。Delphi程序有一个事件函数列表,我们搜索疑似左键点击事件函数的地址0x457FB8,去寻找下该事件函数列表。
事件函数列表如下:
00457B48 . /D07B4500 dd CKme.00457BD0
00457B4C . |0A db 0A
00457B4D . |46 6F 72 6D 4>ascii "FormCreate"
00457B57 |0E db 0E
00457B58 |00 db 00
00457B59 . |407C4500 dd CKme.00457C40
00457B5D . |07 db 07
00457B5E . |63 68 6B 63 6>ascii "chkcode"
00457B65 |0C db 0C
00457B66 |00 db 00
00457B67 . |4C7E4500 dd CKme.00457E4C
00457B6B . |05 db 05
00457B6C . |4B 65 79 55 7>ascii "KeyUp"
00457B71 |15 db 15
00457B72 |00 db 00
00457B73 . |7C7E4500 dd CKme.00457E7C
00457B77 . |0E db 0E
00457B78 . |50 61 6E 65 6>ascii "Panel1DblClick"
00457B86 |12 db 12
00457B87 |00 db 00
00457B88 . |B87F4500 dd CKme.00457FB8
00457B8C . |0B db 0B
00457B8D . |50 61 6E 65 6>ascii "Panel1Click"
可以看出0x00457FB8是Panel1Click函数,即鼠标左键点击事件函数的起始地址,而第二个找到的函数0x00457E7C则是鼠标点击事件函数,但是该函数却无法断下,那么该事件应该本是不可用,然后在某个函数中修改了可用性。
在事件列表中,还可以看到另一个有趣的函数chkcode,看字面意思应该就是检测注册码含义,所以尝试在该函数断下,发现只有在注册码编辑框中输入字符或删除字符即可断在chkcode函数。
在chkcode函数中看到一处跳转,这里应该就是修改右键事件可用性的地方了。
00457D1E |. 8D55 E0 lea edx,[local.8]
00457D21 |. 8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]
00457D27 |. E8 1CB6FCFF call CKme.00423348
00457D2C |. 8B45 E0 mov eax,[local.8]
00457D2F |. 8B93 18030000 mov edx,dword ptr ds:[ebx+0x318]
00457D35 |. E8 52BFFAFF call CKme.00403C8C
00457D3A |. 75 0A jnz short CKme.00457D46
00457D3C |. C783 0C030000>mov dword ptr ds:[ebx+0x30C],0x3E
00457D46 |> 8B83 0C030000 mov eax,dword ptr ds:[ebx+0x30C]
00457D4C |. 83C0 10 add eax,0x10
经过简单单步,在运行到0x00457D35处调用CKme.00403C8C时,可以发现该函数的参数有两个,一个是我们输入的注册码,另一个则是黑头Sun Bird9dseloffc-012-OKtest
。而该函数的作用就是比较注册码,所以正确的注册码就找到了。
而注册码的算法其实也很简单,即:"黑头Sun Bird" + "5 + len(username)" + "dseloffc-012-OK" + username。
值得注意的是,CKme.00457E7C函数并不是鼠标右击点击事件函数,而是鼠标多次点击事件函数,程序的流程是:
在注册码编辑框输入触发chkcode函数,当注册码正确时,修改esi+0x30C的值为0x3E。
然后鼠标多次点击灰框框触发Panel1DblClick函数,将esi+0x30C的值改为0x85。
最后鼠标点击一次灰框框触发鼠标单次点击事件函数,显示朱茵小姐姐的照片,并将鼠标处的提示改为“恭喜恭喜!注册成功”。
所以注册成功的步骤就是输入正确的注册码,然后在灰框框处鼠标点击三次,则就可以出现照片了。