【软件名称】 CRACKME.EXE
【下载地址】 新手博物馆
【保护方式】 注册码
【调试环境】 OllyICE v1.10 修改版,PEiD
【破解日期】 2006-08-16
【破解目的】 研究算法分析
【破文作者】 zhangyonf
【作者声明】 希望向我一样的菜鸟能早日入门,失误之处敬请诸位大侠赐教!
【破解内容】 用PEID查没有加壳,MASM32 / TASM32编写
用OD载入,运行,用GetDlgItemTextA下断,输入注册信息name:zhangzi;serial:123456,点OK中断在这:
004012C4 |. E8 07020000 |call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA程序中断在这
004012C9 |. 83F8 01 |cmp eax, 1 ;
004012CC |. C745 10 EB030>|mov dword ptr [ebp+10], 3EB
004012D3 |.^ 72 CC \jb short 004012A1
004012D5 |. 6A 0B push 0B ; /Count = B (11.)
004012D7 |. 68 7E214000 push 0040217E ; |Buffer = CRACKME.0040217E
004012DC |. 68 E9030000 push 3E9 ; |ControlID = 3E9 (1001.)
004012E1 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
004012E4 |. E8 E7010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012E9 |. B8 01000000 mov eax, 1
004012EE |. EB 07 jmp short 004012F7
004012F0 |> B8 00000000 mov eax, 0
004012F5 |.^ EB 8D jmp short 00401284
004012F7 |> 50 push eax ; /Result
004012F8 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
004012FB |. E8 B2010000 call <jmp.&USER32.EndDialog> ; \EndDialog
.....................
我们一直按F8到这:
00401228 . 68 8E214000 push 0040218E ; ASCII "zhangzi"
; 看到了吧,我们输入的信息都在这呢
0040122D . E8 4C010000 call 0040137E ; 处理name,这儿需要跟进
00401232 . 50 push eax ; eax大写字符的累加
00401233 . 68 7E214000 push 0040217E ; ASCII "123456"
00401238 . E8 9B010000 call 004013D8 ; 处理serial这儿需要跟进
0040123D . 83C4 04 add esp, 4
00401240 . 58 pop eax
00401241 . 3BC3 cmp eax, ebx
00401243 74 07 je short 0040124C ; 关键的一跳
00401245 . E8 18010000 call 00401362
0040124A .^ EB 9A jmp short 004011E6
0040124C > E8 FC000000 call 0040134D ; 成功
00401251 .^ EB 93 jmp short 004011E6
..................
0040122D处跟进来,到这,这儿是对name 的处理
0040137E /$ 8B7424 04 mov esi, [esp+4] ; CRACKME.0040218E
00401382 |. 56 push esi ; 开始处理name
00401383 |> 8A06 /mov al, [esi] ; name第一个字符送al
00401385 |. 84C0 |test al, al
00401387 |. 74 13 |je short 0040139C
00401389 |. 3C 41 |cmp al, 41
0040138B |. 72 1F |jb short 004013AC
0040138D |. 3C 5A |cmp al, 5A
0040138F |. 73 03 |jnb short 00401394 ; 这三句判断是否A<=al<=Z
00401391 |. 46 |inc esi ; 指针加1
00401392 |.^ EB EF |jmp short 00401383 ; 若不在此范围直接去下一个字符
00401394 |> E8 39000000 |call 004013D2 ; 只取>Z的字符处理,这儿主要是将小写字母变为大写
00401399 |. 46 |inc esi ; 指针加1
0040139A |.^ EB E7 \jmp short 00401383
0040139C |> 5E pop esi ; name变为大写
0040139D |. E8 20000000 call 004013C2 ; 处理变为大写后的name 跟进去
004013A2 |. 81F7 78560000 xor edi, 5678 ; 与常数0x5678异或
004013A8 |. 8BC7 mov eax, edi
004013AA |. EB 15 jmp short 004013C1 ; 跳到retn返回
004013AC |> 5E pop esi
004013AD |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013AF |. 68 60214000 push 00402160 ; |Title = "No luck!"
004013B4 |. 68 69214000 push 00402169 ; |Text = "No luck there, mate!"
004013B9 |. FF75 08 push dword ptr [ebp+8] ; |hOwner
004013BC |. E8 79000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
004013C1 \> C3 retn
.....................
0040139D |. E8 20000000 call 004013C2 处跟进来,这里是处理变为大写后的name:
004013C2 /$ 33FF xor edi, edi
004013C4 |. 33DB xor ebx, ebx ; edi,ebx清零
004013C6 |> 8A1E /mov bl, [esi] ; 取大写name的单个字符
004013C8 |. 84DB |test bl, bl ; 测试是否是空
004013CA |. 74 05 |je short 004013D1
004013CC |. 03FB |add edi, ebx ; 往edi累加
004013CE |. 46 |inc esi
004013CF |.^ EB F5 \jmp short 004013C6 ; 取下个大写字符
004013D1 \> C3 retn ; EDI为个大写字符的累加值
这儿是00401394 处的call
004013D2 /$ 2C 20 sub al, 20 ; ASC值减0x20,如果是小写字母的话就变成大写了
004013D4 |. 8806 mov [esi], al ;
004013D6 \. C3 retn
到此对name的处理就快完了,从这返回执行name的最后一步处理,返回到这:
004013A2 |. 81F7 78560000 xor edi, 5678 ; 与常数0x5678异或
004013A8 |. 8BC7 mov eax, edi
004013AA |. EB 15 jmp short 004013C1 ; 跳到retn返回
004013AC |> 5E pop esi
004013AD |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013AF |. 68 60214000 push 00402160 ; |Title = "No luck!"
004013B4 |. 68 69214000 push 00402169 ; |Text = "No luck there, mate!"
004013B9 |. FF75 08 push dword ptr [ebp+8] ; |hOwner
004013BC |. E8 79000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
004013C1 \> C3 retn
到这name的处理就全部完成了,我们总结一下:将输入的name中ASC值大于Z的都减0x20(主要是把小写字符转化为大写),然后将ASC值累加,最后再跟常数0x5678做异或运算。
现在我们继续F8到004013C1 \> C3 retn返回到这:
(到这你应该看到上面你输入的name已经全部变成了大写)
00401232 . 50 push eax ; name的处理结果,入栈
00401233 . 68 7E214000 push 0040217E ; ASCII "123456"
00401238 . E8 9B010000 call 004013D8 ; 处理serial,跟进去
0040123D . 83C4 04 add esp, 4
00401240 . 58 pop eax
00401241 . 3BC3 cmp eax, ebx ;
00401243 74 07 je short 0040124C ; 关键的一跳
00401245 . E8 18010000 call 00401362
0040124A .^ EB 9A jmp short 004011E6
0040124C > E8 FC000000 call 0040134D ; 成功
00401251 .^ EB 93 jmp short 004011E6
..........................
跟进00401238 . E8 9B010000 call 004013D8,到下面这,这儿是对serial的处理:
004013D8 /$ 33C0 xor eax, eax
004013DA |. 33FF xor edi, edi
004013DC |. 33DB xor ebx, ebx ;eax,edi,ebx清零
004013DE |. 8B7424 04 mov esi, [esp+4]
004013E2 |> B0 0A /mov al, 0A ; al=常量0A
004013E4 |. 8A1E |mov bl, [esi] ; 取serial的单个字符
004013E6 |. 84DB |test bl, bl ; 测试是否为空
004013E8 |. 74 0B |je short 004013F5
004013EA |. 80EB 30 |sub bl, 30 ; 字符减常量0x30
004013ED |. 0FAFF8 |imul edi, eax ; 与常数0x30做乘法,乘积放edi(这个指令应该是这样吧,我 ; 查了下指令集,只有带一个参数的,请各位赐教)
004013F0 |. 03FB |add edi, ebx ; 将serial的字符ASC值累加
004013F2 |. 46 |inc esi
004013F3 |.^ EB ED \jmp short 004013E2 ; 取下个字符
004013F5 |> 81F7 34120000 xor edi, 1234
004013FB |. 8BDF mov ebx, edi
004013FD \. C3 retn
从上面可以看出对serial的处理是edi=0,edi=edi*0x30+bl-0x30最后的结果就是再和0x1234异或,然后mov到ebx中返回,返回到这:
040123D . 83C4 04 add esp, 4
00401240 . 58 pop eax
00401241 . 3BC3 cmp eax, ebx ; 比较name和serial的处理结果
00401243 74 07 je short 0040124C ; 关键的一跳,跳向成功
00401245 . E8 18010000 call 00401362
0040124A .^ EB 9A jmp short 004011E6
0040124C > E8 FC000000 call 0040134D ; 成功
00401251 .^ EB 93 jmp short 004011E6
这个crackme的算法就分析完了(其实只要将00401243处的je该成jnz很容易就爆破了,呵呵),注册机我没能写出来,希望哪位大虾能贴出来让我们这些菜鸟学习学习,讲讲思路也行,先谢谢了!
......失误之处敬请诸位大侠赐教!
[培训]科锐软件逆向50期预科班报名即将截止,速来!!! 50期正式班报名火爆招生中!!!