好友
阅读权限30
听众
最后登录1970-1-1
|
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
题目:【吾爱2013CM大赛题目】-- KeyGenMe2013 -- loudy
写一篇,表示对活动的支持;顺便骗点积分!
通常这类目标是很简单的。即使这样,还是认真对待,分享一些经验给新手。
一.了解基本情况
首先需要对目标进行一下静态检查:PE文件头、各区段信息、数据目录表、入口代码等等,以判断是否加壳、目标的编写语言等。
结论是用"Microsoft Visual C++ 6.0"的MFC写的,使用静态连接库,无壳。
很好,可以放开手脚随便调戏了!
先运行目标,看看界面:
从这里可以得到两条有用的信息:
1. 界面大概是基于对话框的;
2. “机器码”(HWID)已经显示出来(已取得),其他输入为“用户名”(Username)和“注册码”(RegCode),应该是硬件绑定的。
那么,需要解决两个问题:a) “机器码”的生成;b) “注册码”的产生。
注:作者的界面使用字体:华文新魏,字号:14。在我的"Windows XP SP3"虚拟机里没有这个字体,很难看,稍微改了一下:字体(Georgia),字号(10),其他稍作调整。
二.机器码的生成
用OD载入目标,CTRL+A分析一下代码,这很重要。
对基于对话框的程序断以下几个API好了:
[Plain Text] 纯文本查看 复制代码 user32.CreateDialogIndirectParamA
user32.CreateDialogIndirectParamW
user32.CreateDialogParamA
user32.CreateDialogParamW
F9运行,停在CreateDialogIndirectParamA,这时栈上:
[Plain Text] 纯文本查看 复制代码 0012FDE4 00417BC8 /CALL to CreateDialogIndirectParamA from KeyGenMe.00417BC2
0012FDE8 00400000 |hInst = 00400000
0012FDEC 0043B458 |pTemplate = KeyGenMe.0043B458
0012FDF0 00000000 |hOwner = NULL
0012FDF4 00417897 |pDlgProc = KeyGenMe.00417897
0012FDF8 00000000 \lParam = 0x0
很好,我们需要pDlgProc,在00417897处F2,F9,停下来:
[Plain Text] 纯文本查看 复制代码 00417897 /$ 817C24 08 10010000 CMP DWORD PTR [ESP+0x8], 0x110 ; WM_INITDIALOG
0041789F |. 75 2B JNZ SHORT 004178CC
004178A1 |. FF7424 04 PUSH DWORD PTR [ESP+0x4] ; OnInitDialog
004178A5 |. E8 DC120000 CALL 00418B86
004178AA |. 50 PUSH EAX
004178AB |. 68 D03B4200 PUSH 00423BD0
004178B0 |. E8 F63C0000 CALL 0041B5AB
004178B5 |. 59 POP ECX
004178B6 |. 85C0 TEST EAX, EAX
004178B8 |. 59 POP ECX
004178B9 |. 74 0C JE SHORT 004178C7
004178BB |. 8B10 MOV EDX, [EAX]
004178BD |. 8BC8 MOV ECX, EAX
004178BF |. FF92 BC000000 CALL NEAR [EDX+0xBC] ; KeyGenMe.00401360
004178C5 |. EB 07 JMP SHORT 004178CE
004178C7 |> 6A 01 PUSH 0x1
004178C9 |. 58 POP EAX
004178CA |. EB 02 JMP SHORT 004178CE
004178CC |> 33C0 XOR EAX, EAX
004178CE \> C2 1000 RETN 0x10
清除断点,在004178BF处F2,F9,跟进00401360里:
[Plain Text] 纯文本查看 复制代码 00401360 . 64:A1 00000000 MOV EAX, FS:[0]
00401366 . 6A FF PUSH -0x1
...
00401420 . 6A 0C PUSH 0xC
00401422 . E8 3C640100 CALL 00417863 ; _malloc,ret EAX=00950090
...
00401452 . E8 09030000 CALL 00401760 ; 关键
...
跟进00401760:
[Plain Text] 纯文本查看 复制代码 00401760 /$ 51 PUSH ECX
00401761 |. 56 PUSH ESI
00401762 |. 6A 00 PUSH 0x0 ; /pFileSystemNameSize = NULL
00401764 |. 6A 00 PUSH 0x0 ; |pFileSystemNameBuffer = NULL
00401766 |. 6A 00 PUSH 0x0 ; |pFileSystemFlags = NULL
00401768 |. 8D4424 10 LEA EAX, [ESP+0x10] ; |0012F8B8
0040176C |. 6A 00 PUSH 0x0 ; |pMaxFilenameLength = NULL
0040176E |. 50 PUSH EAX ; |pVolumeSerialNumber = 0012F8B8
0040176F |. 6A 00 PUSH 0x0 ; |MaxVolumeNameSize = 0x0
00401771 |. 6A 00 PUSH 0x0 ; |VolumeNameBuffer = NULL
00401773 |. 8BF1 MOV ESI, ECX ; |00950090
00401775 |. 68 1CC14200 PUSH 0042C11C ; |RootPathName = "C:\"
0040177A |. FF15 70324200 CALL NEAR [<&KERNEL32.GetVolumeInformationA>]
0012F894 0042C11C |RootPathName = "C:\"
0012F898 00000000 |VolumeNameBuffer = NULL
0012F89C 00000000 |MaxVolumeNameSize = 0x0
0012F8A0 0012F8B8 |pVolumeSerialNumber = 0012F8B8
0012F8A4 00000000 |pMaxFilenameLength = NULL
0012F8A8 00000000 |pFileSystemFlags = NULL
0012F8AC 00000000 |pFileSystemNameBuffer = NULL
0012F8B0 00000000 \pFileSystemNameSize = NULL
called:
0012F8B8 50280A42
00401780 |. 8B4424 04 MOV EAX, [ESP+0x4] ; 50280A42
00401784 |. 0FAFC0 IMUL EAX, EAX ; 75093904
00401787 |. 50 PUSH EAX
00401788 |. 68 18C14200 PUSH 0042C118 ; ASCII "%X"
0040178D |. 56 PUSH ESI
0040178E |. 894424 10 MOV [ESP+0x10], EAX
00401792 |. E8 734C0100 CALL 0041640A
0012F8A8 00950090
0012F8AC 0042C118 ASCII "%X"
0012F8B0 75093904
called:
00950090 00946E98 ASCII "75093904"
00401797 |. 83C4 0C ADD ESP, 0xC
0040179A |. 5E POP ESI
0040179B |. 59 POP ECX
0040179C \. C3 RETN
这样,“机器码”的生成就清楚了:用API KERNEL32.GetVolumeInformationA取逻辑卷"C:"的序列号,相乘,再转成ASCII字符串。
即,“机器码”是在OnInitDialog里生成的。可以这样验证:开一个“命令行窗口”,键入命令DIR,回车得到比如:
[Plain Text] 纯文本查看 复制代码 驱动器 C 中的卷没有标签。
卷的序列号是 5028-0A42
50280A42 x 50280A42 = 75093904
三.注册码的产生
重新载入目标,清除所有断点,F9运行。因为我们不知道注册码的格式,“用户名”和“注册码”随便输入点东西,点“注册”按钮。
得到错误提示:“请填写正确的用户名和注册码!”
在OD里F12暂停,ALT+K打开"Call stack of main thread"窗口:
[Plain Text] 纯文本查看 复制代码 Call stack of main thread
Address Stack Procedure / arguments Called from Frame
------- ----- --------------------- ----------- -----
0012F388 77D19418 Includes ntdll.KiFastSystemCallRet user32.77D19416 0012F3BC
0012F38C 77D2770A user32.WaitMessage user32.77D27705 0012F3BC
0012F3C0 77D249C4 user32.77D2757B user32.77D249BF 0012F3BC
0012F3E8 77D3A956 user32.77D2490E user32.77D3A951 0012F3E4
0012F6A8 77D3A2BC user32.SoftModalMessageBox user32.77D3A2B7 0012F6A4
0012F7F8 77D663FD user32.77D3A147 user32.77D663F8 0012F7F4
0012F850 77D664A2 user32.MessageBoxTimeoutW user32.77D6649D 0012F84C
0012F884 77D50877 ? user32.MessageBoxTimeoutA user32.77D50872 0012F880
0012F8A4 77D5082F ? user32.MessageBoxExA user32.77D5082A 0012F8A0
0012F8A8 003601EE hOwner = 003601EE ('KeyGenMe2013',class='#32770')
0012F8AC 0042C0EC Text = "............................"
0012F8B0 0042C10C Title = "...?..."
0012F8B4 00000000 Style = MB_OK|MB_APPLMODAL
0012F8B8 00000000 LanguageID = 0x0 (LANG_NEUTRAL)
0012F8C0 0041A0A9 ? user32.MessageBoxA KeyGenMe.0041A0A3 0012F8BC
0012F8C4 003601EE hOwner = 003601EE ('KeyGenMe2013',class='#32770')
0012F8C8 0042C0EC Text = "............................"
0012F8CC 0042C10C Title = "...?..."
0012F8D0 00000000 Style = MB_OK|MB_APPLMODAL
0012F8D8 00401666 ? KeyGenMe.0041A07B KeyGenMe.00401661
在反汇编窗口定位到最后一行的00401661,得到以下代码段:
[Plain Text] 纯文本查看 复制代码 004015E0 . 51 PUSH ECX
004015E1 . 53 PUSH EBX
004015E2 . 56 PUSH ESI
004015E3 . 57 PUSH EDI
004015E4 . 8BF1 MOV ESI, ECX
004015E6 . 6A 01 PUSH 0x1
004015E8 . E8 EA910100 CALL 0041A7D7
004015ED . 8B46 60 MOV EAX, [ESI+0x60] ; 用户名
004015F0 . 8D5E 60 LEA EBX, [ESI+0x60]
004015F3 . 68 B0E04200 PUSH 0042E0B0 ; /Arg2 = 0042E0B0
004015F8 . 50 PUSH EAX ; |Arg1
004015F9 . E8 188A0000 CALL 0040A016 ; \KeyGenMe.0040A016
004015FE . 83C4 08 ADD ESP, 0x8
00401601 . 85C0 TEST EAX, EAX
00401603 . 74 77 JE SHORT 0040167C
00401605 . 8B46 68 MOV EAX, [ESI+0x68] ; 注册码
00401608 . 8D7E 68 LEA EDI, [ESI+0x68]
0040160B . 68 B0E04200 PUSH 0042E0B0 ; /Arg2 = 0042E0B0
00401610 . 50 PUSH EAX ; |Arg1
00401611 . E8 008A0000 CALL 0040A016 ; \KeyGenMe.0040A016
00401616 . 83C4 08 ADD ESP, 0x8
00401619 . 85C0 TEST EAX, EAX
0040161B . 74 5F JE SHORT 0040167C
0040161D . 51 PUSH ECX
0040161E . 8BCC MOV ECX, ESP
00401620 . 896424 10 MOV [ESP+0x10], ESP
00401624 . 53 PUSH EBX
00401625 . E8 016B0100 CALL 0041812B
0040162A . 8B4E 5C MOV ECX, [ESI+0x5C] ; 00950090
0040162D . E8 6E010000 CALL 004017A0
00401632 . 51 PUSH ECX
00401633 . 8BCC MOV ECX, ESP
00401635 . 896424 10 MOV [ESP+0x10], ESP
00401639 . 57 PUSH EDI ; 0012FF00
0040163A . E8 EC6A0100 CALL 0041812B
0040163F . 8B4E 5C MOV ECX, [ESI+0x5C] ; 00950090
00401642 . E8 A9010000 CALL 004017F0
00401647 . 8B4E 5C MOV ECX, [ESI+0x5C] ; 00950090
00950090 00946E98 ASCII "75093904",机器码
00950094 00946F38 ASCII "12345678",注册码(假码)
00950098 00946E48 ASCII "MistHill",用户名
0040164A . E8 F1010000 CALL 00401840 ; 关键Call
0040164F . 85C0 TEST EAX, EAX
00401651 . 6A 00 PUSH 0x0
00401653 . 68 0CC14200 PUSH 0042C10C ; 标题:"吾爱破解"
00401658 . 75 11 JNZ SHORT 0040166B ; 转正确
0040165A . 68 ECC04200 PUSH 0042C0EC ; 信息:"请填写正确的用户名和注册码!"
0040165F . 8BCE MOV ECX, ESI
00401661 . E8 158A0100 CALL 0041A07B ; F12 - "Call stack" 指向这里
00401666 . 5F POP EDI
00401667 . 5E POP ESI
00401668 . 5B POP EBX
00401669 . 59 POP ECX
0040166A . C3 RETN
0040166B > 68 D8C04200 PUSH 0042C0D8 ; 信息:"注册成功!您真棒!"
00401670 . 8BCE MOV ECX, ESI
00401672 . E8 048A0100 CALL 0041A07B
00401677 . 5F POP EDI
00401678 . 5E POP ESI
00401679 . 5B POP EBX
0040167A . 59 POP ECX
0040167B . C3 RETN
0040167C > 6A 00 PUSH 0x0
0040167E . 68 0CC14200 PUSH 0042C10C ; 标题:"吾爱破解"
00401683 . 68 C0C04200 PUSH 0042C0C0 ; 信息:"请将注册信息填写完整!"
00401688 . 8BCE MOV ECX, ESI
0040168A . E8 EC890100 CALL 0041A07B
0040168F . 5F POP EDI
00401690 . 5E POP ESI
00401691 . 5B POP EBX
00401692 . 59 POP ECX
00401693 . C3 RETN
显然,00401658处为关键跳,无论你注册算法多么复杂,将其改为:
[Plain Text] 纯文本查看 复制代码 00401658 /EB 11 JMP SHORT 0040166B
就“爆破”了!在实践中,一个好的KeygenMe应尽量避免被“爆破”!
注册算法在00401840里:
[Plain Text] 纯文本查看 复制代码 00401840 /$ 55 PUSH EBP
00401841 |. 8BEC MOV EBP, ESP
00401843 |. 83E4 F8 AND ESP, 0xFFFFFFF8
00401846 |. 83EC 28 SUB ESP, 0x28
00401849 |. 53 PUSH EBX
0040184A |. 55 PUSH EBP
0040184B |. 56 PUSH ESI
0040184C |. 57 PUSH EDI
0040184D |. 8BF1 MOV ESI, ECX
0040184F |. 6A 00 PUSH 0x0
00401851 |. E8 0D6D0100 CALL 00418563 ; 取“机器码”
00401856 |. 6A 00 PUSH 0x0
00401858 |. 8D4E 08 LEA ECX, [ESI+0x8]
0040185B |. 8BD8 MOV EBX, EAX
0040185D |. E8 016D0100 CALL 00418563 ; 取“用户名”
00401862 |. 6A 00 PUSH 0x0
00401864 |. 8D4E 04 LEA ECX, [ESI+0x4]
00401867 |. 8BF8 MOV EDI, EAX
00401869 |. E8 F56C0100 CALL 00418563 ; 取“注册码”
0040186E |. 8BE8 MOV EBP, EAX
00401870 |. 6A 01 PUSH 0x1
00401872 |. 896C24 20 MOV [ESP+0x20], EBP
00401876 |. E8 E85F0100 CALL 00417863 ; _malloc
0040187B |. 8BF0 MOV ESI, EAX
0040187D |. 8A03 MOV AL, [EBX]
0040187F |. 83C4 04 ADD ESP, 0x4
00401882 |. C74424 20 00000000 MOV DWORD PTR [ESP+0x20], 0x0
0040188A |. 84C0 TEST AL, AL
0040188C |. C74424 24 00000000 MOV DWORD PTR [ESP+0x24], 0x0
00401894 |. C74424 28 00000000 MOV DWORD PTR [ESP+0x28], 0x0
0040189C |. C74424 2C 00000000 MOV DWORD PTR [ESP+0x2C], 0x0
004018A4 |. 74 7C JE SHORT 00401922
004018A6 |> 0FBE4B 01 /MOVSX ECX, BYTE PTR [EBX+0x1]
004018AA |. 0FBEC0 |MOVSX EAX, AL
004018AD |. 894424 10 |MOV [ESP+0x10], EAX
004018B1 |. DB4424 10 |FILD DWORD PTR [ESP+0x10]
004018B5 |. 894C24 10 |MOV [ESP+0x10], ECX
004018B9 |. DD5C24 30 |FSTP QWORD PTR [ESP+0x30]
004018BD |. DB4424 10 |FILD DWORD PTR [ESP+0x10]
004018C1 |. 8B4C24 34 |MOV ECX, [ESP+0x34]
004018C5 |. DD5C24 10 |FSTP QWORD PTR [ESP+0x10]
004018C9 |. 8B5424 14 |MOV EDX, [ESP+0x14]
004018CD |. 8B4424 10 |MOV EAX, [ESP+0x10]
004018D1 |. 52 |PUSH EDX
004018D2 |. 8B5424 34 |MOV EDX, [ESP+0x34]
004018D6 |. 50 |PUSH EAX
004018D7 |. 68 32545E40 |PUSH 0x405E5432 ; /Arg4 = 405E5432
004018DC |. 68 87A757CA |PUSH 0xCA57A787 ; |Arg3 = CA57A787
004018E1 |. 51 |PUSH ECX ; |Arg2
004018E2 |. 52 |PUSH EDX ; |Arg1
004018E3 |. 8BCE |MOV ECX, ESI ; |
004018E5 |. E8 D6030000 |CALL 00401CC0 ; \KeyGenMe.00401CC0
004018EA |. 83EC 08 |SUB ESP, 0x8
004018ED |. 8BCE |MOV ECX, ESI ; |
004018EF |. DD1C24 |FSTP QWORD PTR [ESP] ; |
004018F2 |. E8 19020000 |CALL 00401B10 ; \KeyGenMe.00401B10
004018F7 |. DD5C24 30 |FSTP QWORD PTR [ESP+0x30]
004018FB |. 8B4424 34 |MOV EAX, [ESP+0x34]
004018FF |. 8B4C24 30 |MOV ECX, [ESP+0x30]
00401903 |. 8B5424 24 |MOV EDX, [ESP+0x24]
00401907 |. 50 |PUSH EAX ; /Arg4
00401908 |. 8B4424 24 |MOV EAX, [ESP+0x24] ; |
0040190C |. 51 |PUSH ECX ; |Arg3
0040190D |. 52 |PUSH EDX ; |Arg2
0040190E |. 50 |PUSH EAX ; |Arg1
0040190F |. 8BCE |MOV ECX, ESI ; |
00401911 |. E8 FA010000 |CALL 00401B10 ; \KeyGenMe.00401B10
00401916 |. 8A43 01 |MOV AL, [EBX+0x1]
00401919 |. 43 |INC EBX
0040191A |. DD5C24 20 |FSTP QWORD PTR [ESP+0x20] ; 保存结果:双精度浮点数
0040191E |. 84C0 |TEST AL, AL
00401920 |. 75 84 \JNZ SHORT 004018A6 ; 本段循环处理“机器码”
00401922 |> 8A07 MOV AL, [EDI]
00401924 |. 84C0 TEST AL, AL
00401926 |. 74 7C JE SHORT 004019A4
00401928 |> 0FBE57 01 /MOVSX EDX, BYTE PTR [EDI+0x1]
0040192C |. 0FBEC8 |MOVSX ECX, AL
0040192F |. 894C24 10 |MOV [ESP+0x10], ECX
00401933 |. DB4424 10 |FILD DWORD PTR [ESP+0x10]
00401937 |. 895424 10 |MOV [ESP+0x10], EDX
0040193B |. DD5C24 30 |FSTP QWORD PTR [ESP+0x30]
0040193F |. DB4424 10 |FILD DWORD PTR [ESP+0x10]
00401943 |. 8B5424 34 |MOV EDX, [ESP+0x34]
00401947 |. DD5C24 10 |FSTP QWORD PTR [ESP+0x10]
0040194B |. 8B4424 14 |MOV EAX, [ESP+0x14]
0040194F |. 8B4C24 10 |MOV ECX, [ESP+0x10]
00401953 |. 50 |PUSH EAX
00401954 |. 8B4424 34 |MOV EAX, [ESP+0x34]
00401958 |. 51 |PUSH ECX
00401959 |. 68 9EEE9240 |PUSH 0x4092EE9E ; /Arg4 = 4092EE9E
0040195E |. 68 17B7D100 |PUSH 0xD1B717 ; |Arg3 = 00D1B717
00401963 |. 52 |PUSH EDX ; |Arg2
00401964 |. 50 |PUSH EAX ; |Arg1
00401965 |. 8BCE |MOV ECX, ESI ; |
00401967 |. E8 54030000 |CALL 00401CC0 ; \KeyGenMe.00401CC0
0040196C |. 83EC 08 |SUB ESP, 0x8
0040196F |. 8BCE |MOV ECX, ESI ; |
00401971 |. DD1C24 |FSTP QWORD PTR [ESP] ; |
00401974 |. E8 97010000 |CALL 00401B10 ; \KeyGenMe.00401B10
00401979 |. DD5C24 30 |FSTP QWORD PTR [ESP+0x30]
0040197D |. 8B4C24 34 |MOV ECX, [ESP+0x34]
00401981 |. 8B5424 30 |MOV EDX, [ESP+0x30]
00401985 |. 8B4424 2C |MOV EAX, [ESP+0x2C]
00401989 |. 51 |PUSH ECX ; /Arg4
0040198A |. 8B4C24 2C |MOV ECX, [ESP+0x2C] ; |
0040198E |. 52 |PUSH EDX ; |Arg3
0040198F |. 50 |PUSH EAX ; |Arg2
00401990 |. 51 |PUSH ECX ; |Arg1
00401991 |. 8BCE |MOV ECX, ESI ; |
00401993 |. E8 78010000 |CALL 00401B10 ; \KeyGenMe.00401B10
00401998 |. 8A47 01 |MOV AL, [EDI+0x1]
0040199B |. 47 |INC EDI
0040199C |. DD5C24 28 |FSTP QWORD PTR [ESP+0x28] ; 保存结果:双精度浮点数
004019A0 |. 84C0 |TEST AL, AL
004019A2 |. 75 84 \JNZ SHORT 00401928 ; 本段循环处理“用户名”
004019A4 |> 8B5424 2C MOV EDX, [ESP+0x2C]
004019A8 |. 8B4424 28 MOV EAX, [ESP+0x28]
004019AC |. 8B4C24 24 MOV ECX, [ESP+0x24]
004019B0 |. 52 PUSH EDX ; /Arg4
004019B1 |. 8B5424 24 MOV EDX, [ESP+0x24] ; |
004019B5 |. 50 PUSH EAX ; |Arg3
004019B6 |. 51 PUSH ECX ; |Arg2
004019B7 |. 52 PUSH EDX ; |Arg1
004019B8 |. 8BCE MOV ECX, ESI ; |
004019BA |. E8 51010000 CALL 00401B10 ; \KeyGenMe.00401B10
004019BF |. DD5C24 20 FSTP QWORD PTR [ESP+0x20]
004019C3 |. 8BCE MOV ECX, ESI
004019C5 |. E8 A6060000 CALL 00402070
004019CA |. 8B4424 24 MOV EAX, [ESP+0x24]
004019CE |. 8B4C24 20 MOV ECX, [ESP+0x20]
004019D2 |. 83EC 08 SUB ESP, 0x8 ; /
004019D5 |. DD1C24 FSTP QWORD PTR [ESP] ; |Arg3 (8-byte)
004019D8 |. 50 PUSH EAX ; |Arg2
004019D9 |. 51 PUSH ECX ; |Arg1
004019DA |. 8BCE MOV ECX, ESI ; |
004019DC |. E8 DF020000 CALL 00401CC0 ; \KeyGenMe.00401CC0
004019E1 |. E8 32870000 CALL 0040A118 ; __ftol
004019E6 |. 8BC8 MOV ECX, EAX
004019E8 |. BE 08000000 MOV ESI, 0x8
004019ED |> 8D7E 07 /LEA EDI, [ESI+0x7]
004019F0 |. 8BC1 |MOV EAX, ECX
004019F2 |. 33D2 |XOR EDX, EDX
004019F4 |. F7F7 |DIV EDI
004019F6 |. 33D2 |XOR EDX, EDX
004019F8 |. 8BF8 |MOV EDI, EAX
004019FA |. 8BC1 |MOV EAX, ECX
004019FC |. F7F6 |DIV ESI
004019FE |. 33D2 |XOR EDX, EDX
00401A00 |. 03C7 |ADD EAX, EDI
00401A02 |. BF 1A000000 |MOV EDI, 0x1A ; 26.,大写英文字符数
00401A07 |. F7F7 |DIV EDI
00401A09 |. 8A442E F8 |MOV AL, [ESI+EBP-0x8] ; EBP: pRegCode
00401A0D |. 80C2 41 |ADD DL, 0x41 ; “注册码”由字符"A~Z"组成
00401A10 |. 3AC2 |CMP AL, DL ; 比较“注册码”第一组的字符
00401A12 |. 0F85 AC000000 |JNZ 00401AC4 ; 不匹配,跳
00401A18 |. 46 |INC ESI
00401A19 |. 8D56 F8 |LEA EDX, [ESI-0x8]
00401A1C |. 83FA 04 |CMP EDX, 0x4
00401A1F |. 7C CC \JL SHORT 004019ED
00401A21 |. 807D 04 2D CMP BYTE PTR [EBP+0x4], 0x2D ; 分隔符:'-'
00401A25 |. 74 0A JE SHORT 00401A31
00401A27 |. 33C0 XOR EAX, EAX
00401A29 |. 5F POP EDI
00401A2A |. 5E POP ESI
00401A2B |. 5D POP EBP
00401A2C |. 5B POP EBX
00401A2D |. 8BE5 MOV ESP, EBP
00401A2F |. 5D POP EBP
00401A30 |. C3 RETN
00401A31 |> B8 08000000 MOV EAX, 0x8
00401A36 |. BB 05000000 MOV EBX, 0x5
00401A3B |. 2BC5 SUB EAX, EBP
00401A3D |. 8D75 05 LEA ESI, [EBP+0x5]
00401A40 |. 8D3C89 LEA EDI, [ECX+ECX*4]
00401A43 |. 894424 10 MOV [ESP+0x10], EAX
00401A47 |. EB 04 JMP SHORT 00401A4D
00401A49 |> 8B4424 10 /MOV EAX, [ESP+0x10]
00401A4D |> 8D2C30 LEA EBP, [EAX+ESI]
00401A50 |. 8BC1 |MOV EAX, ECX
00401A52 |. 33D2 |XOR EDX, EDX
00401A54 |. F7F5 |DIV EBP
00401A56 |. BD 1A000000 |MOV EBP, 0x1A
00401A5B |. 8BC2 |MOV EAX, EDX
00401A5D |. 33D2 |XOR EDX, EDX
00401A5F |. 03C7 |ADD EAX, EDI
00401A61 |. F7F5 |DIV EBP
00401A63 |. 8A06 |MOV AL, [ESI]
00401A65 |. 80C2 41 |ADD DL, 0x41
00401A68 |. 3AC2 |CMP AL, DL ; 比较“注册码”第二组的字符
00401A6A |. 75 58 |JNZ SHORT 00401AC4 ; 不匹配,跳
00401A6C |. 43 |INC EBX
00401A6D |. 03F9 |ADD EDI, ECX
00401A6F |. 46 |INC ESI
00401A70 |. 83FB 09 |CMP EBX, 0x9
00401A73 |. 7C D4 \JL SHORT 00401A49
00401A75 |. 8B7C24 1C MOV EDI, [ESP+0x1C]
00401A79 |. 807F 09 2D CMP BYTE PTR [EDI+0x9], 0x2D
00401A7D |. 74 0A JE SHORT 00401A89
00401A7F |. 33C0 XOR EAX, EAX
00401A81 |. 5F POP EDI
00401A82 |. 5E POP ESI
00401A83 |. 5D POP EBP
00401A84 |. 5B POP EBX
00401A85 |. 8BE5 MOV ESP, EBP
00401A87 |. 5D POP EBP
00401A88 |. C3 RETN
00401A89 |> BE 5D000000 MOV ESI, 0x5D
00401A8E |> 8D5E 02 /LEA EBX, [ESI+0x2]
00401A91 |. 8BC1 |MOV EAX, ECX
00401A93 |. 33D2 |XOR EDX, EDX
00401A95 |. F7F3 |DIV EBX
00401A97 |. 8BC1 |MOV EAX, ECX
00401A99 |. 8BDA |MOV EBX, EDX
00401A9B |. 33D2 |XOR EDX, EDX
00401A9D |. F7F6 |DIV ESI
00401A9F |. 33D2 |XOR EDX, EDX
00401AA1 |. 03C3 |ADD EAX, EBX
00401AA3 |. BB 1A000000 |MOV EBX, 0x1A
00401AA8 |. F7F3 |DIV EBX
00401AAA |. 8A4437 AD |MOV AL, [EDI+ESI-0x53]
00401AAE |. 80C2 41 |ADD DL, 0x41
00401AB1 |. 3AC2 |CMP AL, DL ; 比较“注册码”第三组的字符
00401AB3 |. 75 0F |JNZ SHORT 00401AC4 ; 不匹配,跳
00401AB5 |. 46 |INC ESI
00401AB6 |. 8D46 AD |LEA EAX, [ESI-0x53]
00401AB9 |. 83F8 0E |CMP EAX, 0xE
00401ABC |. 7C D0 \JL SHORT 00401A8E
00401ABE |. 807F 0E 2D CMP BYTE PTR [EDI+0xE], 0x2D
00401AC2 |. 74 0A JE SHORT 00401ACE
00401AC4 |> 33C0 XOR EAX, EAX ; Invalid,清0返回
00401AC6 |. 5F POP EDI
00401AC7 |. 5E POP ESI
00401AC8 |. 5D POP EBP
00401AC9 |. 5B POP EBX
00401ACA |. 8BE5 MOV ESP, EBP
00401ACC |. 5D POP EBP
00401ACD |. C3 RETN
00401ACE |> BE 0F000000 MOV ESI, 0xF
00401AD3 |> 8BC1 MOV EAX, ECX
00401AD5 |. 33D2 XOR EDX, EDX
00401AD7 |. F7F6 DIV ESI
00401AD9 |. 8BC1 MOV EAX, ECX
00401ADB |. 8BDA MOV EBX, EDX
00401ADD |. 33D2 XOR EDX, EDX
00401ADF |. F7F6 DIV ESI
00401AE1 |. 33D2 XOR EDX, EDX
00401AE3 |. 03C3 ADD EAX, EBX
00401AE5 |. BB 1A000000 MOV EBX, 0x1A
00401AEA |. F7F3 DIV EBX
00401AEC |. 8A043E MOV AL, [ESI+EDI]
00401AEF |. 80C2 41 ADD DL, 0x41
00401AF2 |. 3AC2 CMP AL, DL ; 比较“注册码”第四组的字符
00401AF4 |. 75 CE JNZ SHORT 00401AC4 ; 不匹配,跳
00401AF6 |. 46 INC ESI
00401AF7 |. 83FE 13 CMP ESI, 0x13
00401AFA |. 7C D7 JL SHORT 00401AD3
00401AFC |. 5F POP EDI
00401AFD |. B8 01000000 MOV EAX, 0x1 ; OK/Valid,置1返回
00401B02 |. 5E POP ESI
00401B03 |. 5D POP EBP
00401B04 |. 5B POP EBX
00401B05 |. 8BE5 MOV ESP, EBP
00401B07 |. 5D POP EBP
00401B08 \. C3 RETN
这段代码较长,先根据“机器码”和“用户名”字符串各计算出一个双精度浮点数,再以此两数来计算“注册码”。
由这段代码我们知道,“注册码”的正确格式为:XXXX-XXXX-XXXX-XXXX。各字符取值范围:A~Z。
那些比较实在太明显,实践中也应该避免!
四.写注册机
具体的算法就不用管它了,直接用这段代码来形成我们的“注册机”,它太好“欺负”了!
“注册机”用脚本来实现:
- 在四组比较指令:00401A10、00401A68、00401AB1和00401AF2处,DL含正确的注册码字符;
- 将四处跳转:00401A12、00401A6A、00401AB3和00401AF4改为NOP,以便代码能正常执行;
- 为用户友好,并保证输入的“注册码”有正确格式,脚本会先填写一个“注册码模板”:1111-2222-3333-4444。
- 有效的“注册码”取得后,进行回显。
脚本“注册机”请见附件,感兴趣的可看看里面的注释。
脚本“注册机”使用方法:
1. 在OD里载入目标,并运行脚本,切换到“KeyGenMe2013”的界面:
这时候只需输入“用户名”,点“注册”按钮。
2. 会提示“注册成功!您真棒!”。
3. 正确的“注册码”会显示在编辑框里:RZKP-YYMO-SNTP-UYWB
4. 若要生成其他“用户名”的注册码,需要先点程序的“退出”按钮,然后CTRL+F2重新载入目标,再输入新的用户名,点“注册”按钮。
比如,用户名为:www.52pojie.cn,则注册码为:NZBH-XPHX-DNZW-FHTJ。
这是比较“偷懒”和“取巧”的方法,视回复和关注情况,可能会:
1) 用IDA逆向注册代码段的几个关键函数(浮点计算),再用VC写个注册机。注册算法会比较清晰;
2) 直接利用目标的代码,稍作修改,手工构造一个EXE的注册机。同样不关心具体的注册算法。
|
免费评分
-
查看全部评分
|