cracker这个神圣的职业,一直以来是无数人追求的目标。它的迷人之处就在于深奥性。那种探索未知事物的快感,让多少人深醉其中,无法自拔。记得有位兄弟说过,每天可以不吃饭、不睡觉,却无法不crack。那种攻克难关后的居大成就感,让人难以忘怀。
我在此,就以CrackmeNo2.exe为例,浅述它的分析过程。
一、查壳
这是至关重要的一步,由于壳中用到了许多反调试、反汇编技术,使得我们无法正确分析程序,所以脱掉壳尤为重要。
习惯性的用PEID扫描CrackmeNo2.exe,由图1可知,CrackmeNo2.exe并未加壳,而且还是用Borland Delphi 6.0编写的。没壳当然也就省了脱壳这一步了。
二、OllyDbg动态调试
先试运行CrackmeNo2.exe,随意输入注册码。这里以12345678为例。验证后液晶荧显示“I am sad!”。如图2。
通过查找字符串“I am sad!”,可来到0045143B处。在00451421处有个jnz
条件跳转指令。从00451421处的jnz条件跳转指令可以看出,若跳则会验证失败。不跳则走向光明大道。这是一个关键的跳转,若要爆破,则可以修改此指令。
复制内容到剪贴板
代码:
0045141F |. 3BF0 cmp esi, eax
00451421 |. 75 12 jnz short 00451435 ;关键跳转,成败就在这一瞬间
00451423 |. 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
00451429 |. BA B0144500 mov edx, 004514B0 ; welcome!
0045142E |. E8 6DF3FFFF call 004507A0
00451433 |. EB 10 jmp short 00451445
00451435 |> 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
0045143B |. BA C4144500 mov edx, 004514C4 ; i am sad!
00451440 |. E8 5BF3FFFF call 004507A0在此,我将断点设在call的起始00451380处。按F2键,断点就设好了。接下来,F9运行程序,输入任意注册码进行验证。(这里的注册码必须是数字。)OD中断在刚刚设定的断点处。我们来具体分析反汇编代码,理解注册算法。跟踪算法的过程,是很痛苦的,需要很强的耐心,需要反复多次的调试,才能把算法看懂。
复制内容到剪贴板
代码:
00451380 /. 55 push ebp
00451381 |. 8BEC mov ebp, esp
00451383 |. 6A 00 push 0
00451385 |. 6A 00 push 0
00451387 |. 6A 00 push 0
00451389 |. 53 push ebx
0045138A |. 56 push esi
0045138B |. 8BD8 mov ebx, eax
0045138D |. 33C0 xor eax, eax
0045138F |. 55 push ebp
00451390 |. 68 68144500 push 00451468
00451395 |. 64:FF30 push dword ptr fs:[eax]
00451398 |. 64:8920 mov dword ptr fs:[eax], esp
0045139B |. 8D55 FC lea edx, dword ptr [ebp-4]
0045139E |. 8B83 F4020000 mov eax, dword ptr [ebx+2F4]
004513A4 |. E8 C7E1FDFF call 0042F570
004513A9 |. 837D FC 00 cmp dword ptr [ebp-4], 0 ; 比较用户名是否为空,若为空则要求输入。
004513AD |. 75 15 jnz short 004513C4
004513AF |. 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
004513B5 |. BA 80144500 mov edx, 00451480 ; 请输入用户名
004513BA |. E8 E1F3FFFF call 004507A0
004513BF |. E9 81000000 jmp 00451445
004513C4 |> 8B45 FC mov eax, dword ptr [ebp-4] ; 取用户名字符串
004513C7 |. E8 F830FBFF call 004044C4 ; 得到用户名的长度
004513CC |. 33F6 xor esi, esi
004513CE |. 85C0 test eax, eax
004513D0 |. 7C 11 jl short 004513E3
004513D2 |. 40 inc eax ; 用户名长度加1
004513D3 |. 33D2 xor edx, edx
004513D5 |> 8B4D FC /mov ecx, dword ptr [ebp-4] ; 用户名的地址
004513D8 |. 0FB64C11 FF |movzx ecx, byte ptr [ecx+edx-1]
004513DD |. 03F1 |add esi, ecx
004513DF |. 42 |inc edx
004513E0 |. 48 |dec eax
004513E1 |.^ 75 F2 \jnz short 004513D5
004513E3 |> 8D55 F8 lea edx, dword ptr [ebp-8] ; 试验码
004513E6 |. 8B83 F8020000 mov eax, dword ptr [ebx+2F8]
004513EC |. E8 7FE1FDFF call 0042F570
004513F1 |. 837D F8 00 cmp dword ptr [ebp-8], 0 ; 判断试验码是否为空
004513F5 |. 75 12 jnz short 00451409
004513F7 |. 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
004513FD |. BA 98144500 mov edx, 00451498 ; 请输入注册码
00451402 |. E8 99F3FFFF call 004507A0
00451407 |. EB 3C jmp short 00451445
00451409 8D55 F4 lea edx, dword ptr [ebp-C]
0045140C |. 8B83 F8020000 mov eax, dword ptr [ebx+2F8]
00451412 E8 59E1FDFF call 0042F570 ; 返回试验码长度
00451417 |. 8B45 F4 mov eax, dword ptr [ebp-C]
0045141A |. E8 A16EFBFF call 004082C0
0045141F |. 3BF0 cmp esi, eax ; 将根据注册码生成的值与试验码比较。若相等则 welcome!
00451421 |. 75 12 jnz short 00451435
00451423 |. 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
00451429 |. BA B0144500 mov edx, 004514B0 ; welcome!
0045142E |. E8 6DF3FFFF call 004507A0
00451433 |. EB 10 jmp short 00451445
00451435 |> 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
0045143B |. BA C4144500 mov edx, 004514C4 ; i am sad!
00451440 |. E8 5BF3FFFF call 004507A0
00451445 |> 33C0 xor eax, eax
00451447 |. 5A pop edx
00451448 |. 59 pop ecx
00451449 |. 59 pop ecx
0045144A |. 64:8910 mov dword ptr fs:[eax], edx
0045144D |> 68 6F144500 push 0045146F
00451452 |> 8D45 F4 lea eax, dword ptr [ebp-C]
00451455 |. BA 02000000 mov edx, 2
0045145A |> E8 D12DFBFF call 00404230
0045145F |. 8D45 FC lea eax, dword ptr [ebp-4]
00451462 |. E8 A52DFBFF call 0040420C
00451467 \. C3 retn三、写注算机:
复制内容到剪贴板
代码:
int keygen(char uname[15])
{
int keycode=0;
int nlen=StrLen(uname);
for(int i=0;i<nlen;i++)
{
keycode+=uname;
}
return keycode;
}[
本帖最后由 鹤顶红 于 2007-6-15 16:52 编辑 ]