好友
阅读权限40
听众
最后登录1970-1-1
|
我是用户
发表于 2013-12-15 15:55
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
本帖最后由 我是用户 于 2013-12-16 19:11 编辑
【软件名称】: 【吾爱2013CM大赛解答】-- Crack晓晓
【作者邮箱】: 2714608453@qq.com
【下载地址】: 见论坛
【软件语言】: Borland Delphi 6.0 - 7.0
【使用工具】: OD
【操作平台】: XP SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
1.查壳
丢入PEID,显示为Borland Delphi 6.0 - 7.0。
如图1:
2.分析
丢入DEDE,显示不是Delphi或被加壳了,好吧,那我们就手工来找按钮事件吧。
如图2:
打开程序,如图3:
输入用户名和密码,点击注册,程序无反应。
注册按钮事件代码如下:
很简单,先是获取下用户名和密码,判断是否为空,再判断第一个字符是否为5,如果为5,则触发一个异常,如下代码:
[C++] 纯文本查看 复制代码 0046811C . 3E:0000 add byte ptr [eax], al ; 触发异常。
然后依次判断用户名是否为52PoJie,见如下代码:
[C++] 纯文本查看 复制代码 00468131 . 8B45 FC mov eax, dword ptr [ebp-0x4]
00468134 . 8078 02 50 cmp byte ptr [eax+0x2], 0x50
00468138 . 0F85 BA000000 jnz 004681F8
0046813E . 33C0 xor eax, eax
00468140 . 55 push ebp
00468141 . 68 61814600 push 00468161
00468146 . 64:FF30 push dword ptr fs:[eax]
00468149 . 64:8920 mov dword ptr fs:[eax], esp
0046814C . 8B45 DC mov eax, dword ptr [ebp-0x24]
0046814F . E8 88FDF9FF call <Sysutils::StrToInt(System::AnsiString)>
00468154 . 33C0 xor eax, eax
00468156 . 5A pop edx
00468157 . 59 pop ecx
00468158 . 59 pop ecx
00468159 . 64:8910 mov dword ptr fs:[eax], edx
0046815C . E9 97000000 jmp 004681F8
00468161 .^ E9 72B4F9FF jmp <System::__linkproc__ HandleAnyException(void)>
00468166 . 8B45 F8 mov eax, dword ptr [ebp-0x8]
00468169 . 8078 01 32 cmp byte ptr [eax+0x1], 0x32
0046816D . 0F85 80000000 jnz 004681F3
00468173 . 33C0 xor eax, eax
00468175 . 55 push ebp
00468176 . 68 93814600 push 00468193
0046817B . 64:FF30 push dword ptr fs:[eax]
0046817E . 64:8920 mov dword ptr fs:[eax], esp
00468181 . 8B45 F8 mov eax, dword ptr [ebp-0x8]
00468184 . E8 53FDF9FF call <Sysutils::StrToInt(System::AnsiString)>
00468189 . 33C0 xor eax, eax
0046818B . 5A pop edx
0046818C . 59 pop ecx
0046818D . 59 pop ecx
0046818E . 64:8910 mov dword ptr fs:[eax], edx
00468191 . EB 60 jmp short 004681F3
00468193 .^ E9 40B4F9FF jmp <System::__linkproc__ HandleAnyException(void)>
00468198 . 8B45 F4 mov eax, dword ptr [ebp-0xC]
0046819B . 8078 04 4A cmp byte ptr [eax+0x4], 0x4A
0046819F . 75 4D jnz short 004681EE
004681A1 . 33C0 xor eax, eax
004681A3 . 55 push ebp
004681A4 . 68 C1814600 push 004681C1
004681A9 . 64:FF30 push dword ptr fs:[eax]
004681AC . 64:8920 mov dword ptr fs:[eax], esp
004681AF . 8B45 E4 mov eax, dword ptr [ebp-0x1C]
004681B2 . E8 25FDF9FF call <Sysutils::StrToInt(System::AnsiString)>
004681B7 . 33C0 xor eax, eax
004681B9 . 5A pop edx
004681BA . 59 pop ecx
004681BB . 59 pop ecx
004681BC . 64:8910 mov dword ptr fs:[eax], edx
004681BF . EB 2D jmp short 004681EE
004681C1 .^ E9 12B4F9FF jmp <System::__linkproc__ HandleAnyException(void)>
004681C6 . 8B45 F0 mov eax, dword ptr [ebp-0x10]
004681C9 . 8078 03 6F cmp byte ptr [eax+0x3], 0x6F
004681CD . 75 1A jnz short 004681E9
004681CF . 8B45 EC mov eax, dword ptr [ebp-0x14]
004681D2 . 8078 06 65 cmp byte ptr [eax+0x6], 0x65
004681D6 . 75 11 jnz short 004681E9
004681D8 . 8B45 F4 mov eax, dword ptr [ebp-0xC]
004681DB . 8078 05 69 cmp byte ptr [eax+0x5], 0x69
004681DF . 75 08 jnz short 004681E9
004681E1 . 8B45 DC mov eax, dword ptr [ebp-0x24]
004681E4 . E8 0BFCFFFF call 00467DF4
这里有一点要注意,要对用户名进行判断时要调用StrtoInt来触发异常,如何你输入的是数字,而且数字的大小范围是在Int的范围之间的,
则异常就不会触发,也就无法进行下一步验证。
对密码的验证在004681E4 . E8 0BFCFFFF call 00467DF4这里。
进入00467DF4,我们发现,又触发了一个异常,如下:
[C++] 纯文本查看 复制代码 00467DFE . 6A 00 push 0x0
00467E00 . 49 dec ecx
00467E01 75 52 jnz short 00467E55
00467E03 . 53 push ebx
00467E04 . 56 push esi
00467E05 . 57 push edi
jnz short 00467E55跳转的这个地址其实是错的,他触发一个异常,由于并没有设置顶层异常处理,所以这里的异常会导致验证中止,
也就是说,我们可以推测这个地址是被改写的,OK,我们下写入断点进行查找,找到的代码如下:
[C++] 纯文本查看 复制代码 00468234 > . 53 push ebx ; _TForm1_tmr1Timer
00468235 . 56 push esi
00468236 . 51 push ecx
00468237 . B8 3C804600 mov eax, <_TForm1_btn1Click>
0046823C . BA 58020000 mov edx, 0x258
00468241 . E8 4AFAFFFF call 00467C90 //检测CC断点
00468246 . 48 dec eax
00468247 . 75 2D jnz short 00468276
00468249 . E8 9EDCF9FF call <GetCurrentProcess> ; [GetCurrentProcess
0046824E . 8BD8 mov ebx, eax
00468250 . 54 push esp ; /pOldProtect
00468251 . 6A 40 push 0x40 ; |NewProtect =
PAGE_EXECUTE_READWRITE
00468253 . 68 E8030000 push 0x3E8 ; |Size = 3E8 (1000.)
00468258 . BE F47D4600 mov esi, 00467DF4 ; |入口地址
0046825D . 56 push esi ; |Address => Project1.00467DF4
0046825E . 53 push ebx ; |hProcess
0046825F . E8 E8DDF9FF call <VirtualProtectEx> ; \VirtualProtectEx
00468264 . 54 push esp ; /pBytesWritten
00468265 . 6A 05 push 0x5 ; |BytesToWrite = 0x5
00468267 . 68 20A74600 push 0046A720 ; |Buffer = Project1.0046A720
0046826C . 83C6 0E add esi, 0xE ; |
0046826F . 56 push esi ; |Address => 0x467E02
00468270 . 53 push ebx ; |hProcess
00468271 . E8 F6DDF9FF call <WriteProcessMemory> ; \WriteProcessMemory
00468276 > BE F47D4600 mov esi, 00467DF4 ; 入口地址
0046827B . 8BC6 mov eax, esi
0046827D . BA 64000000 mov edx, 0x64
00468282 . E8 09FAFFFF call 00467C90
00468287 . 48 dec eax
00468288 . 75 2C jnz short 004682B6
0046828A . E8 5DDCF9FF call <GetCurrentProcess> ; [GetCurrentProcess
0046828F . 8BD8 mov ebx, eax
00468291 . 54 push esp ; /pOldProtect
00468292 . 6A 40 push 0x40 ; |NewProtect =
PAGE_EXECUTE_READWRITE
00468294 . 68 E8030000 push 0x3E8 ; |Size = 3E8 (1000.)
00468299 . 68 F47D4600 push 00467DF4 ; |Address = Project1.00467DF4
0046829E . 53 push ebx ; |hProcess
0046829F . E8 A8DDF9FF call <VirtualProtectEx> ; \VirtualProtectEx
004682A4 . 54 push esp ; /pBytesWritten
004682A5 . 6A 05 push 0x5 ; |BytesToWrite = 0x5
004682A7 . 68 20A74600 push 0046A720 ; |Buffer = Project1.0046A720
004682AC . 83C6 0E add esi, 0xE ; |
004682AF . 56 push esi ; |Address
004682B0 . 53 push ebx ; |hProcess
004682B1 . E8 B6DDF9FF call <WriteProcessMemory> ; \WriteProcessMemory
004682B6 > 5A pop edx
004682B7 . 5E pop esi
004682B8 . 5B pop ebx
004682B9 . C3 retn
看到了没,这里是设置了一个定时器,来检测CC断点,如果发现,则改成跳转偏移,我们retn或者进入00467C90这个CALL里将修改标志位,
这两种方法都行。正确的跳转是
[C++] 纯文本查看 复制代码 00467DF4 $ 55 push ebp
00467DF5 . 8BEC mov ebp, esp
00467DF7 . B9 09000000 mov ecx, 0x9
00467DFC > 6A 00 push 0x0
00467DFE . 6A 00 push 0x0
00467E00 . 49 dec ecx
00467E01 ^ 75 F9 jnz short 00467DFC
00467E03 . 53 push ebx
00467E04 . 56 push esi
00467E05 . 57 push edi
00467E06 . 8945 FC mov dword ptr [ebp-0x4], eax
00467E09 . 8B45 FC mov eax, dword ptr [ebp-0x4]
00467E0C . E8 27C5F9FF call <System::__linkproc__ LStrAddRef(void *)>
00467E11 . 33C0 xor eax, eax
00467E13 . 55 push ebp
00467E14 . 68 2B804600 push 0046802B
00467E19 . 64:FF30 push dword ptr fs:[eax]
00467E1C . 64:8920 mov dword ptr fs:[eax], esp
00467E1F . 33C0 xor eax, eax
00467E21 . 55 push ebp
00467E22 . 68 F97F4600 push 00467FF9
00467E27 . 64:FF30 push dword ptr fs:[eax]
00467E2A . 64:8920 mov dword ptr fs:[eax], esp
00467E2D . 8D55 DC lea edx, dword ptr [ebp-0x24]
00467E30 . 8B45 FC mov eax, dword ptr [ebp-0x4]
00467E33 . E8 88C7FEFF call <MD5>
00467E38 . 8B45 DC mov eax, dword ptr [ebp-0x24]
00467E3B . 8D55 E0 lea edx, dword ptr [ebp-0x20]
00467E3E . E8 7DC7FEFF call <MD5>
00467E43 . 8B45 E0 mov eax, dword ptr [ebp-0x20]
00467E46 . 8D55 F8 lea edx, dword ptr [ebp-0x8]
00467E49 . E8 72C7FEFF call <MD5>
00467E4E . 8D45 E8 lea eax, dword ptr [ebp-0x18]
00467E51 . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467E54 . E8 C7C0F9FF call <System::__linkproc__ LStrLAsg(void *,void *)>
00467E59 . 8D45 F0 lea eax, dword ptr [ebp-0x10]
00467E5C . 8B55 E8 mov edx, dword ptr [ebp-0x18]
00467E5F . E8 BCC0F9FF call <System::__linkproc__ LStrLAsg(void *,void *)>
00467E64 . 8D45 EC lea eax, dword ptr [ebp-0x14]
00467E67 . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467E6A . E8 B1C0F9FF call <System::__linkproc__ LStrLAsg(void *,void *)>
00467E6F . 8D45 D8 lea eax, dword ptr [ebp-0x28]
00467E72 . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467E75 . 8A52 1D mov dl, byte ptr [edx+0x1D]
00467E78 . 8850 01 mov byte ptr [eax+0x1], dl
00467E7B . C600 01 mov byte ptr [eax], 0x1
00467E7E . 8D55 D8 lea edx, dword ptr [ebp-0x28]
00467E81 . 8D45 D4 lea eax, dword ptr [ebp-0x2C]
00467E84 . E8 AFABF9FF call <System::__linkproc__ PStrCpy(System::SmallString>
00467E89 . 8D45 D0 lea eax, dword ptr [ebp-0x30]
00467E8C . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467E8F . 8A52 1E mov dl, byte ptr [edx+0x1E]
00467E92 . 8850 01 mov byte ptr [eax+0x1], dl
00467E95 . C600 01 mov byte ptr [eax], 0x1
00467E98 . 8D55 D0 lea edx, dword ptr [ebp-0x30]
00467E9B . 8D45 D4 lea eax, dword ptr [ebp-0x2C]
00467E9E . B1 02 mov cl, 0x2
00467EA0 . E8 63ABF9FF call <System::__linkproc__ PStrNCat(void)>
00467EA5 . 8D55 D4 lea edx, dword ptr [ebp-0x2C]
00467EA8 . 8D45 CC lea eax, dword ptr [ebp-0x34]
00467EAB . E8 88ABF9FF call <System::__linkproc__ PStrCpy(System::SmallString>
00467EB0 . 8D45 D0 lea eax, dword ptr [ebp-0x30]
00467EB3 . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467EB6 . 8A52 1F mov dl, byte ptr [edx+0x1F]
00467EB9 . 8850 01 mov byte ptr [eax+0x1], dl
00467EBC . C600 01 mov byte ptr [eax], 0x1
00467EBF . 8D55 D0 lea edx, dword ptr [ebp-0x30]
00467EC2 . 8D45 CC lea eax, dword ptr [ebp-0x34]
00467EC5 . B1 03 mov cl, 0x3
00467EC7 . E8 3CABF9FF call <System::__linkproc__ PStrNCat(void)>
00467ECC . 8D55 CC lea edx, dword ptr [ebp-0x34]
00467ECF . 8D45 E4 lea eax, dword ptr [ebp-0x1C]
00467ED2 . E8 15C2F9FF call <unknown_libname_66>
00467ED7 . 8B45 E4 mov eax, dword ptr [ebp-0x1C]
00467EDA . E8 FDFFF9FF call <Sysutils::StrToInt(System::AnsiString)>
00467EDF . 83F8 6E cmp eax, 0x6E
00467EE2 . 0F85 07010000 jnz 00467FEF
00467EE8 . 8D45 F4 lea eax, dword ptr [ebp-0xC]
00467EEB . 8B55 EC mov edx, dword ptr [ebp-0x14]
00467EEE . E8 2DC0F9FF call <System::__linkproc__ LStrLAsg(void *,void *)>
00467EF3 . 8D45 C8 lea eax, dword ptr [ebp-0x38]
00467EF6 . 8B55 F4 mov edx, dword ptr [ebp-0xC]
00467EF9 . 8A52 02 mov dl, byte ptr [edx+0x2]
00467EFC . E8 6FC1F9FF call <unknown_libname_63>
00467F01 . 8B45 C8 mov eax, dword ptr [ebp-0x38]
00467F04 . E8 D3FFF9FF call <Sysutils::StrToInt(System::AnsiString)>
00467F09 . 83F8 04 cmp eax, 0x4
00467F0C . 7E 15 jle short 00467F23
00467F0E . 8B45 F8 mov eax, dword ptr [ebp-0x8]
00467F11 . E8 72FEFFFF call 00467D88
00467F16 . 33C0 xor eax, eax
00467F18 . 5A pop edx
00467F19 . 59 pop ecx
00467F1A . 59 pop ecx
00467F1B . 64:8910 mov dword ptr fs:[eax], edx
00467F1E . E9 E0000000 jmp 00468003
00467F23 > 8D45 C4 lea eax, dword ptr [ebp-0x3C]
00467F26 . 8B55 EC mov edx, dword ptr [ebp-0x14]
00467F29 . 8A52 05 mov dl, byte ptr [edx+0x5]
00467F2C . E8 3FC1F9FF call <unknown_libname_63>
00467F31 . 8B45 C4 mov eax, dword ptr [ebp-0x3C]
00467F34 . E8 A3FFF9FF call <Sysutils::StrToInt(System::AnsiString)>
00467F39 . 83F8 05 cmp eax, 0x5
00467F3C . 7D 15 jge short 00467F53
00467F3E . 8B45 F0 mov eax, dword ptr [ebp-0x10]
00467F41 . E8 42FEFFFF call 00467D88
00467F46 . 33C0 xor eax, eax
00467F48 . 5A pop edx
00467F49 . 59 pop ecx
00467F4A . 59 pop ecx
00467F4B . 64:8910 mov dword ptr fs:[eax], edx
00467F4E . E9 B0000000 jmp 00468003
00467F53 > 8D45 D8 lea eax, dword ptr [ebp-0x28]
00467F56 . 8B55 EC mov edx, dword ptr [ebp-0x14]
00467F59 . 8A52 04 mov dl, byte ptr [edx+0x4]
00467F5C . 8850 01 mov byte ptr [eax+0x1], dl
00467F5F . C600 01 mov byte ptr [eax], 0x1
00467F62 . 8D55 D8 lea edx, dword ptr [ebp-0x28]
00467F65 . 8D45 D4 lea eax, dword ptr [ebp-0x2C]
00467F68 . E8 CBAAF9FF call <System::__linkproc__ PStrCpy(System::SmallString>
00467F6D . 8D45 D0 lea eax, dword ptr [ebp-0x30]
00467F70 . 8B55 EC mov edx, dword ptr [ebp-0x14]
00467F73 . 8A52 05 mov dl, byte ptr [edx+0x5]
00467F76 . 8850 01 mov byte ptr [eax+0x1], dl
00467F79 . C600 01 mov byte ptr [eax], 0x1
00467F7C . 8D55 D0 lea edx, dword ptr [ebp-0x30]
00467F7F . 8D45 D4 lea eax, dword ptr [ebp-0x2C]
00467F82 . B1 02 mov cl, 0x2
00467F84 . E8 7FAAF9FF call <System::__linkproc__ PStrNCat(void)>
00467F89 . 8D55 D4 lea edx, dword ptr [ebp-0x2C]
00467F8C . 8D45 CC lea eax, dword ptr [ebp-0x34]
00467F8F . E8 A4AAF9FF call <System::__linkproc__ PStrCpy(System::SmallString>
00467F94 . 8D45 D0 lea eax, dword ptr [ebp-0x30]
00467F97 . 8B55 EC mov edx, dword ptr [ebp-0x14]
00467F9A . 8A52 06 mov dl, byte ptr [edx+0x6]
00467F9D . 8850 01 mov byte ptr [eax+0x1], dl
00467FA0 . C600 01 mov byte ptr [eax], 0x1
00467FA3 . 8D55 D0 lea edx, dword ptr [ebp-0x30]
00467FA6 . 8D45 CC lea eax, dword ptr [ebp-0x34]
00467FA9 . B1 03 mov cl, 0x3
00467FAB . E8 58AAF9FF call <System::__linkproc__ PStrNCat(void)>
00467FB0 . 8D55 CC lea edx, dword ptr [ebp-0x34]
00467FB3 . 8D45 C0 lea eax, dword ptr [ebp-0x40]
00467FB6 . E8 31C1F9FF call <unknown_libname_66>
00467FBB . 8B45 C0 mov eax, dword ptr [ebp-0x40]
00467FBE . E8 19FFF9FF call <Sysutils::StrToInt(System::AnsiString)>
00467FC3 . 3D C6030000 cmp eax, 0x3C6
00467FC8 . 75 25 jnz short 00467FEF
00467FCA . 8D4D B8 lea ecx, dword ptr [ebp-0x48]
00467FCD . BA 04000000 mov edx, 0x4
00467FD2 . B8 6B4F0000 mov eax, 0x4F6B
00467FD7 . E8 D8FEF9FF call <Sysutils::IntToHex(int,int)>
00467FDC . 8B45 B8 mov eax, dword ptr [ebp-0x48]
00467FDF . 8D55 BC lea edx, dword ptr [ebp-0x44]
00467FE2 . E8 D9FCFFFF call 00467CC0
00467FE7 . 8B45 BC mov eax, dword ptr [ebp-0x44]
00467FEA . E8 89F7FBFF call <Dialogs::ShowMessage(System::AnsiString)>
00467FEF > 33C0 xor eax, eax
00467FF1 . 5A pop edx
00467FF2 . 59 pop ecx
00467FF3 . 59 pop ecx
00467FF4 . 64:8910 mov dword ptr fs:[eax], edx
00467FF7 . EB 0A jmp short 00468003
00467FF9 .^ E9 DAB5F9FF jmp <System::__linkproc__ HandleAnyException(void)>
00467FFE . E8 3DB9F9FF call <System::__linkproc__ DoneExcept(void)>
00468003 > 33C0 xor eax, eax
00468005 . 5A pop edx
00468006 . 59 pop ecx
00468007 . 59 pop ecx
00468008 . 64:8910 mov dword ptr fs:[eax], edx
0046800B . 68 32804600 push 00468032
00468010 > 8D45 B8 lea eax, dword ptr [ebp-0x48]
00468013 . BA 05000000 mov edx, 0x5
00468018 . E8 8FBEF9FF call <System::__linkproc__ LStrArrayClr(void *,int)>
0046801D . 8D45 DC lea eax, dword ptr [ebp-0x24]
00468020 . BA 09000000 mov edx, 0x9
00468025 . E8 82BEF9FF call <System::__linkproc__ LStrArrayClr(void *,int)>
0046802A . C3 retn
0046802B .^ E9 5CB8F9FF jmp <unknown_libname_53>
其实一眼就能看出来,密码的验证是对输入的密码进行三重MD5加密,然后在分别取值相加与设定值判断,只能通过暴力猜解了。
如下:
[C++] 纯文本查看 复制代码 md5[30] + md5[31] + md5[32] == 110
md5[5] + md5[6] + md5[7] = 966
md5[3] < 4
md5[6] > 5
3.暴力解密码。
程序用C#写的,代码太乱,勿喷
[C#] 纯文本查看 复制代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace ConsoleApplication1
{
class Program
{
public static string Encrypt(string strPwd)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] data = Encoding.Default.GetBytes(strPwd);
byte[] md5data = md5.ComputeHash(data);
md5.Clear();
string str = "";
for (int i = 0; i < 16; i++)
{
str += md5data[i].ToString("x").PadLeft(2, '0');
}
return str;
}
static void Main(string[] args)
{
string strKey = "a", str1,str2 ;
for (int i = 0; i < 10000000;i++ )
{
strKey = "a" + i.ToString();
String str = Encrypt(Encrypt(Encrypt(strKey)));
str1 = str[29].ToString() + str[30].ToString() + str[31].ToString();
str2 = str[4].ToString() + str[5].ToString() + str[6].ToString();
if (str1 == "110" && str2=="966")
{
Console.WriteLine("true Key is {0}",strKey);
Console.ReadKey();
}
//strKey = strKey+1;
}
Console.WriteLine("未找到");
Console.ReadKey();
}
}
}
成功如下图:
所以正确的一组Key是
用户名:52PoJie
密码:
成功如下图
|
|