首页
社区
课程
招聘
[原创][aCaFeeL之破解我3]破解过程及算法分析
发表于: 2007-5-21 12:23 12000

[原创][aCaFeeL之破解我3]破解过程及算法分析

2007-5-21 12:23
12000

【破文标题】[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[i].
0049D0CE  |.  C1E0 02       |shl     eax, 2                          ;  t[i] <<= 2;
0049D0D1  |.  83E8 02       |sub     eax, 2                          ;  t[i] -= 2
0049D0D4  |.  B9 1B000000   |mov     ecx, 1B
0049D0D9  |.  99            |cdq
0049D0DA  |.  F7F9          |idiv    ecx                             ;  这里是求余,t[i] %= 0x1B
0049D0DC  |.  8BC2          |mov     eax, edx
0049D0DE  |.  83C0 4F       |add     eax, 4F                         ;  t[i] += 0x4F
0049D0E1  |.  8D55 F8       |lea     edx, dword ptr [ebp-8]
0049D0E4  |.  E8 1FB5F6FF   |call    00408608                        ;  里面是个sprintf。sprintf( tmpcode , "%d" , t[i] ) ;
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

到这里基本上爆破的方法和算法都已经看完了.下面动手写下代码就好了:

消息写的代码帖上来:


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (20)
雪    币: 241
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
沙发自己坐 ^_^
2007-5-21 12:23
0
雪    币: 1969
活跃值: (46)
能力值: (RANK:550 )
在线值:
发帖
回帖
粉丝
3
不错的文章,学习了
2007-5-21 13:08
0
雪    币: 261
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
太难了,看不懂  
2007-5-21 15:28
0
雪    币: 707
活跃值: (1301)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
5
不错.........
2007-5-21 16:44
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
6
鼓励一下``

cm作者的贴里有我的算法``呵呵``
帮你顶了`
2007-5-21 17:55
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
zcg
7
写的很详细喔!我顶...
2007-5-21 20:26
0
雪    币: 241
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
有 aCaFeeL 的算发吧。。。
2007-5-22 04:32
0
雪    币: 281
活跃值: (2940)
能力值: ( LV12,RANK:610 )
在线值:
发帖
回帖
粉丝
9
顶一下,不错
2007-5-22 04:35
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
10
多谢楼主
我看到了这句“MessageBox(0,code,0,0);”
然后想到了某件事情。

支持
2007-5-22 09:31
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
11
不错,支持~~~
2007-5-22 09:34
0
雪    币: 241
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
想到了什么事
2007-5-22 15:46
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
对于像我这样的新手来说,分析已经够了,顶
2007-5-24 18:48
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
学习。。。。。
2007-5-25 09:00
0
雪    币: 82
活跃值: (10)
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
15
push 注册码...
2007-5-28 12:46
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
16
什么意思呀?好高深!
2007-5-28 14:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
刚刚学习这方面的东西,请问lz怎么判断的这些strcat,sprintf等这类函数的?
2007-5-29 09:45
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
18
没有什么东西能瞒过 F8 的,能瞒过的只有你的 眼睛 和 知识
2007-5-29 10:02
0
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
19
学不会算法,郁闷ing
2007-5-31 17:24
0
雪    币: 220
活跃值: (12)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
Good job !

有2个问题
1.和楼上的一样 是怎样判定call中内容的呢 ?  就是F7跟进去 一步步的跟吗 ? 有没有更好的办法

2.我用od跟的时候 ‘h’的ascii不是72吗 ? 为什么od中显示的是68呢?

希望能解释下 谢谢 !
2007-6-1 00:07
0
雪    币: 164
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
H=72,h=68
2007-6-1 11:45
0
游客
登录 | 注册 方可回帖
返回
//