- UID
- 42596
注册时间2007-12-22
阅读权限10
最后登录1970-1-1
周游历练
该用户从未签到
|
【标题】:破解Boonz’s CreakMe
【作者】:riusksk(泉哥)
【主页】:[url]http://riusksk.blogbus.com[/url]
【软件】:[url]http://www.ccgcn.com/bbs/attachment.php?aid=431[/url]
【时间】:2009年8月27日星期四
【声明】:纯属技术学习,如有错误之处,烦请指出!
首先用OD载入,F9运行之,在用户名一框中(作者真懒,连用户名,密码之类的字样都懒得写上,只有两个文本框,上框用户名,下框密码)先填上1,看看是否是用户名长度限制,这只是个人习惯而已,至少总比在逆向分析的时候才知道好吧,呵呵……测试结果如下图1:
[img]http://bbs.pediy.com/attachment.php?attachmentid=30373&d=1251370951[/img]
图1
由此可见,用户名长度必须在4—50之间。接着我用”riusksk”作为用户名,密码为”78787878”来分析一下。输入之后,点击check按钮,提示 "Hello, Mr. Badboy!"。我们“查找“->“所有参考文件字串”后,发现这个CM居然是用明码比较的,如下图2所示:
[img]http://bbs.pediy.com/attachment.php?attachmentid=30374&d=1251370951[/img]
图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:[40DCF0],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:[40DCF0] ; |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:[EBP+C],110
00401035 |. 75 7F JNZ SHORT keygenme.004010B6
00401037 |. 6A EC PUSH -14 ; /Index = GWL_EXSTYLE
00401039 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |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:[EBP+8] ; |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:[EBP+8] ; |hWnd
00401060 |. E8 81030000 CALL <JMP.&user32.SetWindowPos> ; \SetWindowPos
00401065 |. 68 D1070000 PUSH 7D1 ; /RsrcName = 2001.
0040106A |. FF35 F0DC4000 PUSH DWORD PTR DS:[40DCF0] ; |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:[EBP+8] ; |hWnd
00401080 |. E8 43030000 CALL <JMP.&user32.SendMessageA> ; \SendMessageA
00401085 |. 68 EE030000 PUSH 3EE ; /ControlID = 3EE (1006.)
0040108A |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |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:[EBP+8]
004010AC |. E8 D6000000 CALL keygenme.00401187
004010B1 |. E9 CB000000 JMP keygenme.00401181
004010B6 |> 817D 0C 01020>CMP DWORD PTR SS:[EBP+C],201
004010BD |. 75 17 JNZ SHORT keygenme.004010D6
004010BF |. FF75 14 PUSH DWORD PTR SS:[EBP+14] ; /lParam
004010C2 |. 6A 02 PUSH 2 ; |wParam = 2
004010C4 |. 68 A1000000 PUSH 0A1 ; |Message = WM_NCLBUTTONDOWN
004010C9 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004010CC |. E8 F7020000 CALL <JMP.&user32.SendMessageA> ; \SendMessageA
004010D1 |. E9 AB000000 JMP keygenme.00401181
004010D6 |> 817D 0C 11010>CMP DWORD PTR SS:[EBP+C],111
004010DD |. 75 7F JNZ SHORT keygenme.0040115E
004010DF |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
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:[EBP+8] ; |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:[EBP+8] ; |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:[EBP+8] ; |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:[40DC86],EAX ; 保存用户名长度
00401217 |. 833D 86DC4000>CMP DWORD PTR DS:[40DC86],4 ; 用户名长度必须大于4
0040121E |. 0F8C 29010000 JL keygenme.0040134D
00401224 |. 833D 86DC4000>CMP DWORD PTR DS:[40DC86],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:[40DC86] ; 将用户名长度转存到EDX
00401242 |> 0FB60439 /MOVZX EAX,BYTE PTR DS:[ECX+EDI] ; 提取用户名各字符u[i]
00401246 |. 83E8 19 |SUB EAX,19 ; u[i]-0x19
00401249 |. 2BD8 |SUB EBX,EAX ; 将上一循环算出的值EBX减去(u[i]-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[i]-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[60];
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[i]-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:
[img]http://bbs.pediy.com/attachment.php?attachmentid=30375&d=1251370951[/img] |
|