riusksk 发表于 2009-8-27 19:46:40

[原创]破解Boonz’s CreakMe

【标题】:破解Boonz’s CreakMe
【作者】:riusksk(泉哥)
【主页】:http://riusksk.blogbus.com
【软件】:http://www.ccgcn.com/bbs/attachment.php?aid=431
【时间】:2009年8月27日星期四
【声明】:纯属技术学习,如有错误之处,烦请指出!


首先用OD载入,F9运行之,在用户名一框中(作者真懒,连用户名,密码之类的字样都懒得写上,只有两个文本框,上框用户名,下框密码)先填上1,看看是否是用户名长度限制,这只是个人习惯而已,至少总比在逆向分析的时候才知道好吧,呵呵……测试结果如下图1:
http://bbs.pediy.com/attachment.php?attachmentid=30373&d=1251370951
                  图1
由此可见,用户名长度必须在4—50之间。接着我用”riusksk”作为用户名,密码为”78787878”来分析一下。输入之后,点击check按钮,提示 "Hello, Mr. Badboy!"。我们“查找“->“所有参考文件字串”后,发现这个CM居然是用明码比较的,如下图2所示:
http://bbs.pediy.com/attachment.php?attachmentid=30374&d=1251370951
                                          图2
单纯找出注册码这不是我们的目的,我们关注的应该是算法。双击提示字符串"Hello, Mr. Badboy!"来到下列地址:
00401000 >/$6A 00         PUSH 0                                 ; /pModule = NULL
00401002|.E8 6D030000   CALL <JMP.&kernel32.GetModuleHandleA>    ; \GetModuleHandleA
00401007|.A3 F0DC4000   MOV DWORD PTR DS:,EAX
0040100C|.6A 00         PUSH 0                                 ; /lParam = NULL
0040100E|.68 2B104000   PUSH keygenme.0040102B                   ; |DlgProc = keygenme.0040102B
00401013|.6A 00         PUSH 0                                 ; |hOwner = NULL
00401015|.68 E9030000   PUSH 3E9                                 ; |pTemplate = 3E9
0040101A|.FF35 F0DC4000 PUSH DWORD PTR DS:               ; |hInst = 00400000
00401020|.E8 79030000   CALL <JMP.&user32.DialogBoxParamA>       ; \DialogBoxParamA
00401025|.50            PUSH EAX                                 ; /ExitCode
00401026\.E8 43030000   CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess
0040102B/.55            PUSH EBP
0040102C|.8BEC          MOV EBP,ESP
0040102E|.817D 0C 10010>CMP DWORD PTR SS:,110
00401035|.75 7F         JNZ SHORT keygenme.004010B6
00401037|.6A EC         PUSH -14                                 ; /Index = GWL_EXSTYLE
00401039|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
0040103C|.E8 75030000   CALL <JMP.&user32.GetWindowLongA>      ; \GetWindowLongA
00401041|.0D 00000800   OR EAX,80000
00401046|.50            PUSH EAX                                 ; /NewValue
00401047|.6A EC         PUSH -14                                 ; |Index = GWL_EXSTYLE
00401049|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
0040104C|.E8 8F030000   CALL <JMP.&user32.SetWindowLongA>      ; \SetWindowLongA
00401051|.6A 03         PUSH 3                                 ; /Flags = SWP_NOSIZE|SWP_NOMOVE
00401053|.6A 00         PUSH 0                                 ; |Height = 0
00401055|.6A 00         PUSH 0                                 ; |Width = 0
00401057|.6A 00         PUSH 0                                 ; |Y = 0
00401059|.6A 00         PUSH 0                                 ; |X = 0
0040105B|.6A FF         PUSH -1                                  ; |InsertAfter = HWND_TOPMOST
0040105D|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
00401060|.E8 81030000   CALL <JMP.&user32.SetWindowPos>          ; \SetWindowPos
00401065|.68 D1070000   PUSH 7D1                                 ; /RsrcName = 2001.
0040106A|.FF35 F0DC4000 PUSH DWORD PTR DS:               ; |hInst = 00400000
00401070|.E8 47030000   CALL <JMP.&user32.LoadIconA>             ; \LoadIconA
00401075|.50            PUSH EAX                                 ; /lParam
00401076|.6A 01         PUSH 1                                 ; |wParam = 1
00401078|.68 80000000   PUSH 80                                  ; |Message = WM_SETICON
0040107D|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
00401080|.E8 43030000   CALL <JMP.&user32.SendMessageA>          ; \SendMessageA
00401085|.68 EE030000   PUSH 3EE                                 ; /ControlID = 3EE (1006.)
0040108A|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
0040108D|.E8 18030000   CALL <JMP.&user32.GetDlgItem>            ; \GetDlgItem
00401092|.50            PUSH EAX                                 ; /hWnd
00401093|.E8 3C030000   CALL <JMP.&user32.SetFocus>            ; \SetFocus
00401098|.6A 01         PUSH 1                                 ; /Arg3 = 00000001
0040109A|.68 F88B0000   PUSH 8BF8                              ; |Arg2 = 00008BF8
0040109F|.68 00504000   PUSH keygenme.00405000                   ; |Arg1 = 00405000
004010A4|.E8 6D030000   CALL keygenme.00401416                   ; \keygenme.00401416
004010A9|.FF75 08       PUSH DWORD PTR SS:
004010AC|.E8 D6000000   CALL keygenme.00401187
004010B1|.E9 CB000000   JMP keygenme.00401181
004010B6|>817D 0C 01020>CMP DWORD PTR SS:,201
004010BD|.75 17         JNZ SHORT keygenme.004010D6
004010BF|.FF75 14       PUSH DWORD PTR SS:               ; /lParam
004010C2|.6A 02         PUSH 2                                 ; |wParam = 2
004010C4|.68 A1000000   PUSH 0A1                                 ; |Message = WM_NCLBUTTONDOWN
004010C9|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
004010CC|.E8 F7020000   CALL <JMP.&user32.SendMessageA>          ; \SendMessageA
004010D1|.E9 AB000000   JMP keygenme.00401181
004010D6|>817D 0C 11010>CMP DWORD PTR SS:,111
004010DD|.75 7F         JNZ SHORT keygenme.0040115E
004010DF|.8B45 10       MOV EAX,DWORD PTR SS:
004010E2|.3D F3030000   CMP EAX,3F3
004010E7|.75 41         JNZ SHORT keygenme.0040112A
004010E9|.6A 28         PUSH 28                                  ; /Count = 28 (40.)             《=我们在这边下断点
004010EB|.68 F8DC4000   PUSH keygenme.0040DCF8                   ; |Buffer = keygenme.0040DCF8
004010F0|.68 EE030000   PUSH 3EE                                 ; |ControlID = 3EE (1006.)
004010F5|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
004010F8|.E8 B3020000   CALL <JMP.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA
004010FD|.6A 28         PUSH 28                                  ; /Count = 28 (40.)
004010FF|.68 F8DE4000   PUSH keygenme.0040DEF8                   ; |Buffer = keygenme.0040DEF8
00401104|.68 EF030000   PUSH 3EF                                 ; |ControlID = 3EF (1007.)
00401109|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
0040110C|.E8 9F020000   CALL <JMP.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA
00401111|.E8 F2000000   CALL keygenme.00401208                                                 《=加密算法在这里,我们跟进去
00401116|.68 F8DF4000   PUSH keygenme.0040DFF8                   ; /Text = "Hello, Mr. Badboy!"    《=停在这边
0040111B|.68 EF030000   PUSH 3EF                                 ; |ControlID = 3EF (1007.)
00401120|.FF75 08       PUSH DWORD PTR SS:                ; |hWnd
00401123|.E8 A6020000   CALL <JMP.&user32.SetDlgItemTextA>       ; \SetDlgItemTextA
00401128|.EB 57         JMP SHORT keygenme.00401181
0040112A|>3D F0030000   CMP EAX,3F0
0040112F|.75 16         JNZ SHORT keygenme.00401147
00401131|.6A 00         PUSH 0                                 ; /Style = MB_OK|MB_APPLMODAL
00401133|.68 61DC4000   PUSH keygenme.0040DC61                   ; |Title = "NFO"
00401138|.68 2ADC4000   PUSH keygenme.0040DC2A                   ; |Text = "KeygenMe #1
重新载入运行,断下后,一直单步到00401111,然后跟进CALL keygenme.00401208,我们来到这里:

00401208/$68 F8DC4000   PUSH keygenme.0040DCF8                   ; /String = "riusksk"
0040120D|.E8 80010000   CALL <JMP.&kernel32.lstrlenA>            ; \lstrlenA
00401212|.A3 86DC4000   MOV DWORD PTR DS:,EAX            ;保存用户名长度
00401217|.833D 86DC4000>CMP DWORD PTR DS:,4            ;用户名长度必须大于4
0040121E|.0F8C 29010000 JL keygenme.0040134D
00401224|.833D 86DC4000>CMP DWORD PTR DS:,32             ;用户名长度必须小于0x32
0040122B|.0F8F 1C010000 JG keygenme.0040134D
00401231|.33C0          XOR EAX,EAX                              ;清零
00401233|.33DB          XOR EBX,EBX
00401235|.33C9          XOR ECX,ECX
00401237|.BF F8DC4000   MOV EDI,keygenme.0040DCF8                ;ASCII "riusksk"
0040123C|.8B15 86DC4000 MOV EDX,DWORD PTR DS:            ;将用户名长度转存到EDX
00401242|>0FB60439      /MOVZX EAX,BYTE PTR DS:         ;提取用户名各字符u
00401246|.83E8 19       |SUB EAX,19                              ;u-0x19
00401249|.2BD8          |SUB EBX,EAX                           ;将上一循环算出的值EBX减去(u-0x19),EBX初始为0
0040124B|.41            |INC ECX                                 ;ECX为计数器
0040124C|.3BCA          |CMP ECX,EDX                           ;依次循环处理各用户名字符
0040124E|.^ 75 F2         \JNZ SHORT keygenme.00401242
00401250|.53            PUSH EBX                                 ; //<%lX> = FFFFFDA3,循环处理后的结果S1,注意这里的格式为大写字母
00401251|.68 F8DB4000   PUSH keygenme.0040DBF8                   ; |Format = "%lX"
00401256|.68 F8E04000   PUSH keygenme.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
00401267|.33C9          XOR ECX,ECX
00401269|.03C3          ADD EAX,EBX                              ;将结果S1保存到EAX
0040126B|.0FAFC3      IMUL EAX,EBX                           ;S1平方
0040126E|.03C8          ADD ECX,EAX                              ;ECX=S1^2
00401270|.2BD3          SUB EDX,EBX                              ; S1取反
00401272|.33D0          XOR EDX,EAX                              ;S1取反后的值与S1异或运算
00401274|.0FAFD8      IMUL EBX,EAX                           ;S1^3
00401277|.53            PUSH EBX                                 ; //<%lX> = F2CD03FB,结果S2
00401278|.68 F8DB4000   PUSH keygenme.0040DBF8                   ; |Format = "%lX"
0040127D|.68 F8E14000   PUSH keygenme.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,keygenme.0040E0F8                ;ASCII "FFFFFDA3"
00401297|.03D8          ADD EBX,EAX                              ;
00401299|.33CB          XOR ECX,EBX                              ;
0040129B|.0FAFCB      IMUL ECX,EBX                           ;40E0F8平方
0040129E|.2BC8          SUB ECX,EAX                              ;40E0F8-S1
004012A0|.51            PUSH ECX                                 ; //<%lX> = 41720F48,结果S3
004012A1|.68 F8DB4000   PUSH keygenme.0040DBF8                   ; |Format = "%lX"
004012A6|.68 F8E24000   PUSH keygenme.0040E2F8                   ; |s = keygenme.0040E2F8
004012AB|.E8 E8000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
004012B0|.83C4 0C       ADD ESP,0C
004012B3|.68 FCDB4000   PUSH keygenme.0040DBFC                   ; /Format = "Bon-"
004012B8|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |s = keygenme.0040DDF8
004012BD|.E8 D6000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
004012C2|.83C4 08       ADD ESP,8
004012C5|.68 F8E04000   PUSH keygenme.0040E0F8                   ; /StringToAdd = "FFFFFDA3"
004012CA|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |ConcatString = "Bon-FFFFFDA3-F2CD03FB-41720F48"
004012CF|.E8 B2000000   CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA
004012D4|.68 01DC4000   PUSH keygenme.0040DC01                   ; /StringToAdd = "-"
004012D9|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |ConcatString = "Bon-FFFFFDA3-F2CD03FB-41720F48"
004012DE|.E8 A3000000   CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA
004012E3|.68 F8E14000   PUSH keygenme.0040E1F8                   ; /StringToAdd = "F2CD03FB"
004012E8|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |ConcatString = "Bon-FFFFFDA3-F2CD03FB-41720F48"
004012ED|.E8 94000000   CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA
004012F2|.68 01DC4000   PUSH keygenme.0040DC01                   ; /StringToAdd = "-"
004012F7|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |ConcatString = "Bon-FFFFFDA3-F2CD03FB-41720F48"
004012FC|.E8 85000000   CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA
00401301|.68 F8E24000   PUSH keygenme.0040E2F8                   ; /StringToAdd = "41720F48"
00401306|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |ConcatString = "Bon-FFFFFDA3-F2CD03FB-41720F48"
0040130B|.E8 76000000   CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA
00401310|.B8 F8DD4000   MOV EAX,keygenme.0040DDF8                ;将S1,S2,S3和Bon连接成Bon-S1-S2-S3,作为最后的密码
00401315|.BB F8DE4000   MOV EBX,keygenme.0040DEF8                ;ASCII "78787878"
0040131A|.53            PUSH EBX                                 ; /String2 => "78787878"
0040131B|.50            PUSH EAX                                 ; |String1 => "Bon-FFFFFDA3-F2CD03FB-41720F48"
0040131C|.E8 6B000000   CALL <JMP.&kernel32.lstrcmpA>            ; \lstrcmpA
00401321|.74 15         JE SHORT keygenme.00401338               ;这里直接NOP掉,即可暴破
00401323|.68 17DC4000   PUSH keygenme.0040DC17                   ; /Format = "Hello, Mr. Badboy!"
00401328|.68 F8DF4000   PUSH keygenme.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 keygenme.0040DC03                   ; /Format = "Hello, Mr. Goodboy!"
0040133D|.68 F8DF4000   PUSH keygenme.0040DFF8                   ; |s = keygenme.0040DFF8
00401342|.E8 51000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
00401347|.83C4 08       ADD ESP,8
0040134A|.33C0          XOR EAX,EAX
0040134C|.C3            RETN
0040134D|>6A 28         PUSH 28                                  ; /Length = 28 (40.)
0040134F|.68 F8DD4000   PUSH keygenme.0040DDF8                   ; |Destination = keygenme.0040DDF8
00401354|.E8 21000000   CALL <JMP.&kernel32.RtlZeroMemory>       ; \RtlZeroMemory
00401359|.68 65DC4000   PUSH keygenme.0040DC65                   ; /Format = "Name must be 4 - 50 chars long!"
0040135E|.68 F8DF4000   PUSH keygenme.0040DFF8                   ; |s = keygenme.0040DFF8
00401363|.E8 30000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
00401368|.83C4 08       ADD ESP,8
0040136B|.33C0          XOR EAX,EAX
0040136D\.C3            RETN

算法总结:
1.用户名长度必须在4-50之间
2. S1=0
for (i=0;i< lstrlen(u);i++)
{S1=S1-(u-0x19) }
3. S2=S1^3
4. S3=40E0F8*40E0F8-40E0F8=41720F48
5. password=Bon-S1-S2-S3
这里提供一组有效注册码:
用户名:riusksk
序列号:Bon-FFFFFDA3-F2CD03FB-41720F48

注册机源码:

#include "stdio.h"

void main()
{
char username;
int ulen;
int i=0;
unsigned long S1=0;
unsigned long S2;
unsigned long S3=0x41720F48

printf("please input your name:");
gets(username);
ulen=strlen(username);
if (ulen<4 || ulen>50)
    printf("Name must be 4 - 50 chars long!\n");
else
{

   for(i=0;i<ulen;i++)
    {
       S1=S1-(username-0x19);
    }
   S2=S1*S1*S1;

   printf("\nYour serial is Bon-%lX-%lX-%lX",S1,S2,S3);
   printf("\nMade By riusksk\n\n\n");
   return;
}
}
测试结果如图3:
http://bbs.pediy.com/attachment.php?attachmentid=30375&d=1251370951

老万 发表于 2009-8-27 20:52:13

分析的真详细,学习了。

MyCracker 发表于 2009-9-11 15:10:56

来看看,学习下,支持你

野猫III 发表于 2009-10-11 17:51:56

图片看不到了。。。支持的说!

算法注册机我这边总是编译不成功,不知何解。

[ 本帖最后由 野猫III 于 2009-10-11 18:16 编辑 ]

binke 发表于 2009-10-11 18:36:51

回复 4# 野猫III 的帖子

/:11 1.缺少;
2.未定义变量

qifeon 发表于 2009-10-11 18:39:00

原帖由 野猫III 于 2009-10-11 17:51 发表 https://www.chinapyg.com/images/common/back.gif
图片看不到了。。。支持的说!

算法注册机我这边总是编译不成功,不知何解。
1、unsigned long S3=0x41720F48
少个分号
2、头文件缺少
#include "string.h"
3、for(i=0;i<ulen;i++)
    {
       S1=S1-(username-0x19);
    }
应该为for(i=0;i<ulen;i++)
    {
       S1=S1-(username-0x19);
    }代码被处理了,论坛原因。
楼主把源码设置为插入代码即可。

[ 本帖最后由 qifeon 于 2009-10-11 18:42 编辑 ]

野猫III 发表于 2009-10-11 19:30:55

原帖由 qifeon 于 2009-10-11 18:39 发表 https://www.chinapyg.com/images/common/back.gif

1、unsigned long S3=0x41720F48
少个分号
2、头文件缺少
#include "string.h"
3、for(i=0;i

谢谢青牛,我这改了也一样,用的是Dev C++,你带个源码上来给我下载试试。。。

qifeon 发表于 2009-10-11 19:57:42

有事才看到猫哥的帖子。/:013
附件里注册机加源代码。
页: [1]
查看完整版本: [原创]破解Boonz’s CreakMe