申请ID:haoshuaioo
邮箱:bbmu@qq.com
看雪精华:https://bbs.pediy.com/thread-44958.htm
[size=1.4][原创][aCaFeeL之破解我3]破解过程及算法分析 [color=rgba(134, 142, 150, 0.8) !important] 2007-5-21 12:23 [color=rgba(134, 142, 150, 0.8) !important] 10676[color=rgba(134, 142, 150, 0.8) !important][url=] 申请推荐此帖[/url] [color=rgba(134, 142, 150, 0.8) !important][url=] 举报[/url] [color=rgba(134, 142, 150, 0.8) !important] 编辑 [size=1.1]
【破文标题】[aCaFeeL之破解我3]破解过程及算法分析
【对 象】跟我一样刚能看懂汇编语言的朋友(-_-!!)
【下载地址】http://bbs.pediy.com/attachment.php?attachmentid=5292&d=1176823661
【原文地址】http://bbs.pediy.com/showthread.php?t=42896
【破解工具】OD+PEID
【保护方式】序号
【任 务】爆破,算法
【破文作者】haoshuaioo
【组 织】没有
【破解声明】第一次鼓起勇气发帖,写的不好还望大家多多包涵。
【 MSN 】haoshuaioo@hotmail.com
【破解过程】
1. 下载程序(^_^)
http://bbs.pediy.com/attachment.php?attachmentid=5292&d=1176823661
2. 解压缩查壳
peid 显示 [Borland Delphi 4.0 - 5.0] 无壳 .
3. OD直接启动
OD加载后会停在程序入口:
0049D468 > $ 55 push ebp
0049D469 . 8BEC mov ebp, esp
0049D46B . 83C4 F4 add esp, -0C
0049D46E . B8 B8D24900 mov eax, 0049D2B8 ; 5
0049D473 . E8 1C92F6FF call 00406694
0049D478 . A1 C0FC4900 mov eax, dword ptr [49FCC0]
0049D47D . 8B00 mov eax, dword ptr [eax]
0049D47F . E8 0C24FBFF call 0044F890
0049D484 . 8B0D BCFD4900 mov ecx, dword ptr [49FDBC] ; 破解我3.004A08E8
0049D48A . A1 C0FC4900 mov eax, dword ptr [49FCC0]
0049D48F . 8B00 mov eax, dword ptr [eax]
0049D491 . 8B15 64CE4900 mov edx, dword ptr [49CE64] ; 破解我3.0049CEB0
0049D497 . E8 0C24FBFF call 0044F8A8
……
不管它,F9直接跑起来.
程序启动,(界面挺漂亮,哈哈).随便输入注册名和验校码(为什么是"验校码" -_-!!).
我输入的是 haoshuaioo , 1234567891 .点注册,提示:[加油,注册不成功!]
一定要记住这几个字哟!有用的,忽忽。
回到OD,插件-> Ultra String Reference -> Find ANSII .
找找有没有[加油,注册不成功!]的字样。
找到:
Ultra String Reference, 条目 350
Address=0049D1C3
Disassembly=mov eax, 0049D224
Text String=加油,注册不成功!
双击跟踪到CPU窗口。
0049D19A |. E8 516DF6FF call 00403EF0
0049D19F |. 75 17 jnz short 0049D1B8 ; 要爆破的就在这里下手吧。^_^
0049D1A1 |. 6A 00 push 0 ; /Arg1 = 00000000
0049D1A3 |. 66:8B0D FCD14>mov cx, word ptr [49D1FC] ; |
0049D1AA |. B2 02 mov dl, 2 ; |
0049D1AC |. B8 08D24900 mov eax, 0049D208 ; |恭喜,注册成功了!
0049D1B1 |. E8 C6A2FBFF call 0045747C ; \破解我3.0045747C
0049D1B6 |. EB 15 jmp short 0049D1CD
0049D1B8 |> 6A 00 push 0 ; /Arg1 = 00000000
0049D1BA |. 66:8B0D FCD14>mov cx, word ptr [49D1FC] ; |
0049D1C1 |. B2 01 mov dl, 1 ; |
0049D1C3 |. B8 24D24900 mov eax, 0049D224 ; |加油,注册不成功!
0049D1C8 |. E8 AFA2FBFF call 0045747C ; \破解我3.0045747C
很明显看到成功与不成功只有一个 jnz 的距离啊.
在这里往上翻,找到函数过程开始的地方,F2下断,然后再点[注册].就会断在过程入口.如下:
0049D134 /. 55 push ebp ; 过程入口,这里F2下断。
0049D135 |. 8BEC mov ebp, esp
0049D137 |. 6A 00 push 0
0049D139 |. 6A 00 push 0
0049D13B |. 6A 00 push 0
0049D13D |. 53 push ebx
0049D13E |. 8BD8 mov ebx, eax
0049D140 |. 33C0 xor eax, eax
0049D142 |. 55 push ebp
0049D143 |. 68 F0D14900 push 0049D1F0
0049D148 |. 64:FF30 push dword ptr fs:[eax]
0049D14B |. 64:8920 mov dword ptr fs:[eax], esp
0049D14E |. 8D55 FC lea edx, dword ptr [ebp-4]
0049D151 |. 8B83 DC020000 mov eax, dword ptr [ebx+2DC]
0049D157 |. E8 3038F9FF call 0043098C ; 取注册名
0049D15C |. 8B55 FC mov edx, dword ptr [ebp-4]
0049D15F |. B8 F0084A00 mov eax, 004A08F0 ; ASCII "??
0049D164 |. E8 4B6AF6FF call 00403BB4 ; 保存注册名到 4A08F0
0049D169 |. 8D55 F8 lea edx, dword ptr [ebp-8]
0049D16C |. 8B83 D8020000 mov eax, dword ptr [ebx+2D8]
0049D172 |. E8 1538F9FF call 0043098C ; 取输入注册码
0049D177 |. 8B55 F8 mov edx, dword ptr [ebp-8]
0049D17A |. B8 F4084A00 mov eax, 004A08F4 ; ASCII "??
0049D17F |. E8 306AF6FF call 00403BB4 ; 保存注册码到 4A08F4
0049D184 |. 8D55 F4 lea edx, dword ptr [ebp-C]
0049D187 |. A1 F0084A00 mov eax, dword ptr [4A08F0] ; 取注册名
0049D18C |. E8 FBFEFFFF call 0049D08C ; 算法!!!!
0049D191 |. 8B45 F4 mov eax, dword ptr [ebp-C] ; 真注册码
0049D194 |. 8B15 F4084A00 mov edx, dword ptr [4A08F4] ; 输入的注册码
0049D19A |. E8 516DF6FF call 00403EF0
0049D19F |. 75 17 jnz short 0049D1B8 ; 关键跳转咯,可以爆破.
0049D1A1 |. 6A 00 push 0 ; /Arg1 = 00000000
0049D1A3 |. 66:8B0D FCD14>mov cx, word ptr [49D1FC] ; |
0049D1AA |. B2 02 mov dl, 2 ; |
0049D1AC |. B8 08D24900 mov eax, 0049D208 ; |恭喜,注册成功了!
0049D1B1 |. E8 C6A2FBFF call 0045747C ; \破解我3.0045747C
0049D1B6 |. EB 15 jmp short 0049D1CD
0049D1B8 |> 6A 00 push 0 ; /Arg1 = 00000000
0049D1BA |. 66:8B0D FCD14>mov cx, word ptr [49D1FC] ; |
0049D1C1 |. B2 01 mov dl, 1 ; |
0049D1C3 |. B8 24D24900 mov eax, 0049D224 ; |加油,注册不成功!
0049D1C8 |. E8 AFA2FBFF call 0045747C ; \破解我3.0045747C
0049D1CD |> 33C0 xor eax, eax
0049D1CF |. 5A pop edx
0049D1D0 |. 59 pop ecx
0049D1D1 |. 59 pop ecx
0049D1D2 |. 64:8910 mov dword ptr fs:[eax], edx
0049D1D5 |. 68 F7D14900 push 0049D1F7
0049D1DA |> 8D45 F4 lea eax, dword ptr [ebp-C]
0049D1DD |. E8 7E69F6FF call 00403B60
0049D1E2 |. 8D45 F8 lea eax, dword ptr [ebp-8]
0049D1E5 |. BA 02000000 mov edx, 2
0049D1EA |. E8 9569F6FF call 00403B84
0049D1EF \. C3 retn
上面就是整个函数过程,下面来看下算法到底是怎么回事,
0049D18C |. E8 FBFEFFFF call 0049D08C 这个call跟进去:
0049D08C /$ 55 push ebp
0049D08D |. 8BEC mov ebp, esp
0049D08F |. 83C4 F8 add esp, -8
0049D092 |. 53 push ebx
0049D093 |. 56 push esi
0049D094 |. 33C9 xor ecx, ecx
0049D096 |. 894D F8 mov dword ptr [ebp-8], ecx
0049D099 |. 8BF2 mov esi, edx
0049D09B |. 8945 FC mov dword ptr [ebp-4], eax
0049D09E |. 8B45 FC mov eax, dword ptr [ebp-4]
0049D0A1 |. E8 EE6EF6FF call 00403F94
0049D0A6 |. 33C0 xor eax, eax
0049D0A8 |. 55 push ebp
0049D0A9 |. 68 14D14900 push 0049D114
0049D0AE |. 64:FF30 push dword ptr fs:[eax]
0049D0B1 |. 64:8920 mov dword ptr fs:[eax], esp
0049D0B4 |. 8D45 FC lea eax, dword ptr [ebp-4] ; 又看到注册名了
0049D0B7 |. BA 2CD14900 mov edx, 0049D12C ; 固定字符:aCaFeeL
0049D0BC |. E8 276DF6FF call 00403DE8 ; 这里是一个 strcat ,将输入的注册名与aCaFeeL连接。
0049D0C1 |. BB 01000000 mov ebx, 1 ; 算法开始
0049D0C6 |> 8B45 FC /mov eax, dword ptr [ebp-4] ; 将连接好的字符有效地址传给eax。
0049D0C9 |. 0FB64418 FF |movzx eax, byte ptr [eax+ebx-1] ; 依次取连接后字符每一位,姑且写成 t.
0049D0CE |. C1E0 02 |shl eax, 2 ; t <<= 2;
0049D0D1 |. 83E8 02 |sub eax, 2 ; t -= 2
0049D0D4 |. B9 1B000000 |mov ecx, 1B
0049D0D9 |. 99 |cdq
0049D0DA |. F7F9 |idiv ecx ; 这里是求余,t %= 0x1B
0049D0DC |. 8BC2 |mov eax, edx
0049D0DE |. 83C0 4F |add eax, 4F ; t += 0x4F
0049D0E1 |. 8D55 F8 |lea edx, dword ptr [ebp-8]
0049D0E4 |. E8 1FB5F6FF |call 00408608 ; 里面是个sprintf。sprintf( tmpcode , "%d" , t ) ;
0049D0E9 |. 8B55 F8 |mov edx, dword ptr [ebp-8]
0049D0EC |. 8BC6 |mov eax, esi
0049D0EE |. E8 F56CF6FF |call 00403DE8 ; 将计算好的 code 追加到注册码的末尾。strcat(注册码,tmpcode);
0049D0F3 |. 43 |inc ebx ; 计数器+1
0049D0F4 |. 83FB 08 |cmp ebx, 8 ; 比较计数器
0049D0F7 |.^ 75 CD \jnz short 0049D0C6 ; 不到达循环次数就跳过去继续执行。一共是7次。
0049D0F9 |. 33C0 xor eax, eax
0049D0FB |. 5A pop edx
0049D0FC |. 59 pop ecx
0049D0FD |. 59 pop ecx
0049D0FE |. 64:8910 mov dword ptr fs:[eax], edx
0049D101 |. 68 1BD14900 push 0049D11B
0049D106 |> 8D45 F8 lea eax, dword ptr [ebp-8]
0049D109 |. BA 02000000 mov edx, 2
0049D10E |. E8 716AF6FF call 00403B84
0049D113 \. C3 retn
到这里基本上爆破的方法和算法都已经看完了.下面动手写下代码就好了:
消息写的代码帖上来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
CrackMe3Keygen( char * regName )
{
const char * m_name = "aCaFeeL" ;
char name[100] = {0} , code[100] = {0} ;
wsprintf( name , "%s" , regName ) ;
strcat( name , m_name ) ;
for ( int i = 0 ; i < strlen(s) ; i ++ )
{
char tmp[10]={0} ;
char t = s ;
/* // 这里可以优化一下写成 ((t<<2)-2)%0x1B+0x4F.
t = t << 2 ;
t = t - 2 ;
t = t % 0x1B ;
t += 0x4F
*/
wsprintf( tmp , "%d" , ((t<<2)-2)%0x1B+0x4F ) ;
strcat( code , tmp ) ;
}
MessageBox(0,code,0,0);
}
|
至此整个破解过程已经完毕,希望能给像我一样不太懂破解的朋友一些灵感.
附上注册信息:
haoshuaioo
888789105888687 |