首页
社区
课程
招聘
[原创]boonz's Keygenme #1 初学者分析笔记
发表于: 2009-8-14 17:54 5417

[原创]boonz's Keygenme #1 初学者分析笔记

2009-8-14 17:54
5417

boonz's Keygenme #1 初学者分析笔记 (头一次发破文)

该Crackme来自pediy crackme 2007
在Crackme 2007中破解作者ainafeng已经给出了大概的破解流程。不过太简要了,作为初学者,我花了3天的功夫重新研究了一下这个crackme,下面是我自己的Crack过程,因为我是新手中的新手,OH NO!,所以只能挑这种最简单的Crame破解。这也是我第一次写破文,请各位多多指点校正,谢谢各位!
和我一样级别的朋友请仔细看注解,如果一点都看不懂请先看王爽著的"汇编语言",我就是看了两天才开始Crack的,欢迎大家一起研究讨论。
这个crackme是明码比较的,现在已经非常稀少了,断一下就可以直接看到真的注册码了,但是对于我而言直接看码只是爆破的水平,而且也没什么意义,研究算法才真的有意义!
不费话了,正式开始了!
使用工具:PEID,OD
先打开Crackme
第一个文本框输入yangchunyu
第二个文本框输入1234567890
点check,提示Hello, Mr. Badboy!
用PEID看无壳,OD载入,串参考,看到Hello, Mr. Badboy!
别急,慢慢向上看,一直到这里,下断,F9运行再次输入,第一个文本框输入yangchunyu,第二个文本框输入1234567890,点check,断下了,然后F8往下走,如下:

00401208  /$  68 F8DC4000   push    0040DCF8                         ; /String = "yangchunyu"
0040120D  |.  E8 80010000   call    <jmp.&kernel32.lstrlenA>         ; \lstrlenA
跟进这个call看看取得用户名长度的代码
跟到这里
7C80BDC2    8B45 08         mov     eax, dword ptr [ebp+8]           ; keygenme.0040DCF8
7C80BDC5    85C0            test    eax, eax
7C80BDC7    0F84 68A80200   je      7C836635
7C80BDCD    8365 FC 00      and     dword ptr [ebp-4], 0
7C80BDD1    8D50 01         lea     edx, dword ptr [eax+1]              
7C80BDD4    8A08            mov     cl, byte ptr [eax]               | 把"yangchunyu"中的字符挨个送过去
7C80BDD6    40              inc     eax                              | 下一个
7C80BDD7    84C9            test    cl, cl                           
7C80BDD9  ^ 75 F9           jnz     short 7C80BDD4                   | 没干完活继续回到7C80BDD4继续干
7C80BDDB    2BC2            sub     eax, edx
7C80BDDD    834D FC FF      or      dword ptr [ebp-4], FFFFFFFF
7C80BDE1    E8 1B67FFFF     call    7C802501
7C80BDE6    C2 0400         retn    4
从call返回到这里了
00401212  |.  A3 86DC4000   mov     dword ptr [40DC86], eax          | EAX里是用户名长度,这里是A
00401217  |.  833D 86DC4000>cmp     dword ptr [40DC86], 4            | 看看用户名长度是否小于4
0040121E  |.  0F8C 29010000 jl      0040134D                         | 小于则跳走
00401224  |.  833D 86DC4000>cmp     dword ptr [40DC86], 32           | 再看看用户名长度是否大于50
0040122B  |.  0F8F 1C010000 jg      0040134D                         | 大于也不行
00401231  |.  33C0          xor     eax, eax                         \
00401233  |.  33DB          xor     ebx, ebx                         | 都满足了开始寄存器清零
00401235  |.  33C9          xor     ecx, ecx                         /
00401237  |.  BF F8DC4000   mov     edi, 0040DCF8                    ;  ASCII "yangchunyu"      把用户名的地址赋给edi留着后面用
0040123C  |.  8B15 86DC4000 mov     edx, dword ptr [40DC86]          / 把用户名长度放到edx里
00401242  |>  0FB60439      /movzx   eax, byte ptr [ecx+edi]         | 把用户名第一个字节字符送到eax里
00401246  |.  83E8 19       |sub     eax, 19                         | EAX=EAX-19=79-19=60
00401249  |.  2BD8          |sub     ebx, eax                        | EBX=EBX-EAX=0-79("y")
0040124B  |.  41            |inc     ecx                             | 下一个字符
0040124C  |.  3BCA          |cmp     ecx, edx                        | 看看到没到最后一个字符
0040124E  |.^ 75 F2         \jnz     short 00401242                  \ 没干完活跳回去继续干!!

把我用的注册名yangchunyu按字符挨个走一遍
"y"=79,"a"=61,"n"=6E,"g"=67,"c"=63,"h"=68,"u"=75,"n"=6E,"y"=79,"u"=75
于是有EBX=0-("y"-19)-("a"-19)-("n"-19)-("g"-19)-("c"-19)-("h"-19)-("u"-19)-("n"-19)-("y"-19)-("u"-19)=FFFFFCAF

00401250  |.  53            push    ebx                              ; /<%lX> = FFFFFCAF 把这个中间值1压栈保存
00401251  |.  68 F8DB4000   push    0040DBF8                         ; |%lx
00401256  |.  68 F8E04000   push    0040E0F8                         ; |s = keygenme.0040E0F8
0040125B  |.  E8 38010000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA

00401260  |.  83C4 0C       add     esp, 0C
00401263  |.  33C0          xor     eax, eax                         \
00401265  |.  33D2          xor     edx, edx                         |-寄存器清零开始下一段(注意没有清EBX)
00401267  |.  33C9          xor     ecx, ecx                         /
00401269  |.  03C3          add     eax, ebx                         | EAX=EAX+EBX=FFFFFCAF
0040126B  |.  0FAFC3        imul    eax, ebx                         | EAX=EAX*EBX=FFFFFCAF*FFFFFCAF=000AFFA1
0040126E  |.  03C8          add     ecx, eax                         | ECX=ECX+EAX=0+000AFFA1=000AFFA1
00401270  |.  2BD3          sub     edx, ebx                         | EDX=EDX-EBX=0-FFFFFCAF=00000351
00401272  |.  33D0          xor     edx, eax                         | EDX=EDX XOR EAX=00000351 XOR 000AFFA1=000AFCF0
00401274  |.  0FAFD8        imul    ebx, eax                         | EBX=EBX*EAX=FFFFFCAF*000AFFA1=DB863B0F(结果为AFFA0DB863B0F只能存32位)
00401277  |.  53            push    ebx                              ; /<%lX> 把中间值2压栈保存
00401278  |.  68 F8DB4000   push    0040DBF8                         ; |%lx
0040127D  |.  68 F8E14000   push    0040E1F8                         ; |s = keygenme.0040E1F8
00401282  |.  E8 11010000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
00401287  |.  83C4 0C       add     esp, 0C
0040128A  |.  33C0          xor     eax, eax                           /
0040128C  |.  33DB          xor     ebx, ebx                           | 寄存器清零
0040128E  |.  33D2          xor     edx, edx                           |
00401290  |.  33C9          xor     ecx, ecx                           \
00401292  |.  B8 F8E04000   mov     eax, 0040E0F8                    ;  ASCII "FFFFFCAF"(注意这次是把装FFFFFCAF的内存地址当作数值赋给了EAX)
00401297  |.  03D8          add     ebx, eax                           | EBX=EBX+EAX=0+EAX=0040E0F8
00401299  |.  33CB          xor     ecx, ebx                           | ECX=ECX XOR EBX=0 XOR EBX =EBX=0040E0F8
0040129B  |.  0FAFCB        imul    ecx, ebx                           | ECX=ECX*EBX=0040E0F8*0040E0F8=3DA4E100
0040129E  |.  2BC8          sub     ecx, eax                           | ECX=ECX-EAX=41B2F040-0040E0F8=41720F48
004012A0  |.  51            push    ecx                              ; /<%lX> ECX=41720F48 把这个中间值3压栈保存
004012A1  |.  68 F8DB4000   push    0040DBF8                         ; |%lx
004012A6  |.  68 F8E24000   push    0040E2F8                         ; |s = keygenme.0040E2F8
004012AB  |.  E8 E8000000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
004012B0  |.  83C4 0C       add     esp, 0C
004012B3  |.  68 FCDB4000   push    0040DBFC                         ; /bon- 把内存0040DBFC中的字符也就是"bon-"压栈保存
004012B8  |.  68 F8DD4000   push    0040DDF8                         ; |s = keygenme.0040DDF8
004012BD  |.  E8 D6000000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
004012C2  |.  83C4 08       add     esp, 8
004012C5  |.  68 F8E04000   push    0040E0F8                         ; /StringToAdd = "FFFFFCAF"
004012CA  |.  68 F8DD4000   push    0040DDF8                         ; |ConcatString = "Bon-"
004012CF  |.  E8 B2000000   call    <jmp.&kernel32.lstrcatA>         ; \lstrcatA

跟进这个call,代码如下
7C834D41 >  6A 08           push    8
7C834D43    68 904D837C     push    7C834D90
7C834D48    E8 79D7FCFF     call    7C8024C6
7C834D4D    8365 FC 00      and     dword ptr [ebp-4], 0
7C834D51    8B45 0C         mov     eax, dword ptr [ebp+C]
7C834D54    8BD0            mov     edx, eax
7C834D56    8A08            mov     cl, byte ptr [eax]
7C834D58    40              inc     eax
7C834D59    84C9            test    cl, cl
7C834D5B  ^ 75 F9           jnz     short 7C834D56
7C834D5D    2BC2            sub     eax, edx
7C834D5F    8BF2            mov     esi, edx                          | 注意这里:把"FFFFFCAF"的地址0040E0F8赋给了esi
7C834D61    8BD0            mov     edx, eax
7C834D63    8B7D 08         mov     edi, dword ptr [ebp+8]            | 把Bon_字符串所在内存的首地址0040DDF8赋给edi
7C834D66    4F              dec     edi                               | 往前数一个地址
7C834D67    8D47 01         lea     eax, dword ptr [edi+1]            | 再加回来
7C834D6A    8A4F 01         mov     cl, byte ptr [edi+1]              | "Bon_"挨个走一遍
7C834D6D    47              inc     edi                               | 走一遍加一个数
7C834D6E    84C9            test    cl, cl                            | 看看走没走完
7C834D70  ^ 75 F8           jnz     short 7C834D6A                    | 没走完接着走
7C834D72    8BCA            mov     ecx, edx                     | 现在edi=edi+len("bon_")=edi+4也就是定位到了"Bon_"内存地址的后面第一个地址
7C834D74    C1E9 02         shr     ecx, 2
7C834D77    F3:A5           rep     movs dword ptr es:[edi], dword ptr [esi]     |关键语句!:把FFFFFCAF放到Bon_后边,注意:edi,esi也同时变化
7C834D79    8BCA            mov     ecx, edx
7C834D7B    83E1 03         and     ecx, 3
7C834D7E    F3:A4           rep     movs byte ptr es:[edi], byte ptr [esi]       |此时[esi]内容为空
7C834D80    834D FC FF      or      dword ptr [ebp-4], FFFFFFFF
7C834D84    E8 78D7FCFF     call    7C802501
7C834D89    C2 0800         retn    8

返回了此时0040DDF8地址开始的字符串已经是"Bon-FFFFFCAF"了

004012D4  |.  68 01DC4000   push    0040DC01                                     ; /-
004012D9  |.  68 F8DD4000   push    0040DDF8                                     ; |ConcatString = "Bon-FFFFFCAF-"
004012DE  |.  E8 A3000000   call    <jmp.&kernel32.lstrcatA>   算法见上边call    ; \lstrcatA
004012E3  |.  68 F8E14000   push    0040E1F8                                     ; /StringToAdd = "DB863B0F"
004012E8  |.  68 F8DD4000   push    0040DDF8                                     ; |ConcatString = "Bon-FFFFFCAF-DB863B0F"
004012ED  |.  E8 94000000   call    <jmp.&kernel32.lstrcatA>   算法见上边call    ; \lstrcatA
004012F2  |.  68 01DC4000   push    0040DC01                                     ; /-
004012F7  |.  68 F8DD4000   push    0040DDF8                                     ; |ConcatString = "Bon-FFFFFCAF-DB863B0F-"
004012FC  |.  E8 85000000   call    <jmp.&kernel32.lstrcatA>   算法见上边call    ; \lstrcatA
00401301  |.  68 F8E24000   push    0040E2F8                                     ; /StringToAdd = "41720F48"
00401306  |.  68 F8DD4000   push    0040DDF8                                     ; |ConcatString = "Bon-FFFFFCAF-DB863B0F-41720F48"
0040130B  |.  E8 76000000   call    <jmp.&kernel32.lstrcatA>   算法见上边call    ; \lstrcatA
00401310  |.  B8 F8DD4000   mov     eax, 0040DDF8                                ;  ASCII "Bon-FFFFFCAF-DB863B0F-41720F48"
00401315  |.  BB F8DE4000   mov     ebx, 0040DEF8                                ;  ASCII "1234567890"
0040131A  |.  53            push    ebx                                          ; /String2 => "1234567890"
0040131B  |.  50            push    eax                                          ; |String1 = "Bon-FFFFFCAF-DB863B0F-41720F48"
把假码和真码都压栈了
开始最后的比较了
0040131C  |.  E8 6B000000   call    <jmp.&kernel32.lstrcmpA>                     ; \lstrcmpA  一看就是串比较 关键Call!
00401321  |.  74 15         je      short 00401338                                  | 相等就hello, mr. goodboy! 不等就hello, mr. badboy!
00401323  |.  68 17DC4000   push    0040DC17                                     ; /hello, mr. badboy!
00401328  |.  68 F8DF4000   push    0040DFF8                                     ; |s = keygenme.0040DFF8
0040132D  |.  E8 66000000   call    <jmp.&user32.wsprintfA>                      ; \wsprintfA
00401332  |.  83C4 08       add     esp, 8
00401335  |.  33C0          xor     eax, eax
00401337  |.  C3            retn
00401338  |>  68 03DC4000   push    0040DC03                                     ; /hello, mr. goodboy!
0040133D  |.  68 F8DF4000   push    0040DFF8                                     ; |s = keygenme.0040DFF8

算法总结

1.注册名长度应该介于4-50之间
2.中间数值1=19*(用户名长度)再依次减用户名的ASCII值
3.中间数值2=中间数值1的立方;
4.中间数值3=40E0F8*40E0F8-40E0F8=41720F48为常数
5.注册名格式="Bon-"中间数值1-中间数值2-中间数值3

我的注册码:

注册名: yangchunyu

序列号: Bon-FFFFFCAF-DB863B0F-41720F48

下面是用vb写的注册机

Private Sub Command1_Click()

If Len(Text1.Text) < 4 Or Len(Text1.Text) > 50 Then
MsgBox ("用户名长度应该介于4到50之间,请重新输入")
Text1.Text = ""
Text2.Text = ""
Exit Sub
End If
Dim UsrName As String
UsrName = Text1.Text
Dim NameAscCount As Integer
NameAscCount = 0

For i = 1 To Len(UsrName)
    NameAscCount = NameAscCount + Asc(Mid(UsrName, i, 1))
Next i

Dim Sn1, Sn2, Sn3, Sn As String
Sn1 = Hex(25 * Len(UsrName) - NameAscCount)
Sn2 = Hex((25 * Len(UsrName) - NameAscCount) ^ 3)
Sn3 = "41720F48"
Sn = "Bon-" & Sn1 & "-" & Sn2 & "-" & Sn3
Text2.Text = Sn
End Sub

终于完活了,我的Crack功力增长1,经验增长1。:) 谢谢阅读!

Hmm..鼻子好难受,明天去医院抽血化验过敏原。

杨春雨于2009年8月13日晚20:32


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 215
活跃值: (15)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
不错,再接再厉
2009-8-16 21:05
0
雪    币: 97697
活跃值: (200839)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
Support.
2009-8-16 21:10
0
游客
登录 | 注册 方可回帖
返回
//