本帖最后由 zcc1414 于 2013-12-14 01:25 编辑
-------------------------------------------------【文章简介】-------------------------------------------------
【文章标题】 【吾爱2013CM大赛题目】--CrackMe -- 苏紫方璇 CM分析
【文章作者】 zcc1414
【作者邮箱】 无~
【作者主页】 无~
【软件名称】 CrackMe
【软件大小】 44.0 KB (45,056 字节)
【下载地址】 http://www.52pojie.cn/thread-228417-1-1.html
【加壳方式】 无~
【保护方式】 无~
【编写语言】 VC
【使用工具】 OD
【操作平台】 XPSP3
【软件介绍】 吾爱2013CM大赛题目
【作者声明】 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
-------------------------------------------------【文章正文】-------------------------------------------------
大家好 我是zcc1414 小菜好久没爆破了 今天来爆破+追码 分析就留给其他做吧
小菜不懂怎么截图 就直接放文本了
如果不懂的同学可以看下断 我的补丁上的断点分析
成功图片:
无码的:
好吧 R 大 喜欢有码的:
吾爱补丁:
提供一组正确码:
0012F738 00383D50 ASCII "abcdef"
0012F73C 0012F798 ASCII "919394969799"
总结:
程序 设置两个TIMER过程 对各个函数进行CC检测 防止对函数进行下断点
程序用了几种防调试的办法
验证时用到了SEH异常跳转去到另外地点验证这种方法值得提倡
运行程序 修改代码就会退出 发现有TIMER过程
发现有线索了 timer 但是程序退出了 回溯代码找到下面这些 发现设置了 两个TIEMR过程 下面的检测断点是都是检测 CC断点
[C++] 纯文本查看 复制代码 下面的检测断点是检测 CC断点
00401381 . FF15 20304000 call dword ptr ds:[<&KERNEL32.LoadLibraryA>] ; |\LoadLibraryA
00401387 . 50 push eax ; |hModule
00401388 . FF15 00304000 call dword ptr ds:[<&KERNEL32.GetProcAddress>] ; \GetProcAddress
0040138E . 6A 14 push 0x14 ; 上面动态获得SetTimer函数
00401390 . 50 push eax
00401391 . E8 DA040000 call CrackMe.00401870 ; 监视是否对SetTimer下断点 如果有则退出
00401396 . 83C4 08 add esp,0x8
00401399 . 85C0 test eax,eax
0040139B EB 05 jmp XCrackMe.004013A2 ; 这里我已经修改成为jmp 后面也是一样
0040139D . E8 BE040000 call CrackMe.00401860 ; 退出
004013A2 > 68 9E000000 push 0x9E
004013A7 . 68 A0184000 push CrackMe.004018A0 ; ↑@@
004013AC . E8 BF040000 call CrackMe.00401870 ; 监视是否对SendMessage下断点
004013B1 . 83C4 08 add esp,0x8
004013B4 . 85C0 test eax,eax
004013B6 EB 05 jmp XCrackMe.004013BD ; 修改成为jmp
004013B8 . E8 A3040000 call CrackMe.00401860 ; 退出
004013BD > 68 2C020000 push 0x22C
004013C2 . 68 50194000 push CrackMe.00401950
004013C7 . E8 A4040000 call CrackMe.00401870 ; 监视是否对SendMessage下断点
004013CC . 83C4 08 add esp,0x8
004013CF . 85C0 test eax,eax
004013D1 EB 05 jmp XCrackMe.004013D8 ; 修改成为jmp
004013D3 . E8 88040000 call CrackMe.00401860 ; 退出
004013D8 > E8 97090000 call <jmp.&MFC42.#1175>
004013DD . 85C0 test eax,eax
004013DF . 74 09 je XCrackMe.004013EA
004013E1 . 8B10 mov edx,dword ptr ds:[eax]
004013E3 . 8BC8 mov ecx,eax
004013E5 . FF52 7C call dword ptr ds:[edx+0x7C]
004013E8 . EB 02 jmp XCrackMe.004013EC
004013EA > 33C0 xor eax,eax
004013EC > 8B40 20 mov eax,dword ptr ds:[eax+0x20]
004013EF . 8B35 00324000 mov esi,dword ptr ds:[<&USER32.SetTimer>] ; USER32.SetTimer
004013F5 . 68 50194000 push CrackMe.00401950 ; /Timerproc = CrackMe.00401950
004013FA . 68 E8030000 push 0x3E8 ; |Timeout = 1000. ms
004013FF . 6A 01 push 0x1 ; |TimerID = 1
00401401 . 50 push eax ; |hWnd
00401402 . FFD6 call esi ; \SetTimer
00401404 . E8 6B090000 call <jmp.&MFC42.#1175>
00401409 . 85C0 test eax,eax
0040140B . 74 09 je XCrackMe.00401416
0040140D . 8B10 mov edx,dword ptr ds:[eax]
0040140F . 8BC8 mov ecx,eax
00401411 . FF52 7C call dword ptr ds:[edx+0x7C]
00401414 . EB 02 jmp XCrackMe.00401418
00401416 > 33C0 xor eax,eax
00401418 > 8B40 20 mov eax,dword ptr ds:[eax+0x20]
0040141B . 68 A0184000 push CrackMe.004018A0 ; ↑@@
00401420 . 68 E8030000 push 0x3E8
00401425 . 6A 02 push 0x2
00401427 . 50 push eax
00401428 . FFD6 call esi ; USER32.SetTimer
0040142A . 5F pop edi
0040142B . B8 01000000 mov eax,0x1
00401430 . 5E pop esi
00401431 . 83C4 18 add esp,0x18
00401434 . C3 retn
然后开始往后分析 timer回调函数
[C++] 纯文本查看 复制代码 004018A0 . A1 FC404000 mov eax,dword ptr ds:[0x4040FC] ; timer1
004018A5 . 56 push esi
004018A6 . 8B35 0C304000 mov esi,dword ptr ds:[<&KERNEL32.QueryPerformanceCounter>] ; kernel32.7C80A4B7
004018AC . 85C0 test eax,eax
004018AE . 7C 23 jl XCrackMe.004018D3
004018B0 . 7F 09 jg XCrackMe.004018BB
004018B2 . A1 F8404000 mov eax,dword ptr ds:[0x4040F8]
004018B7 . 85C0 test eax,eax
004018B9 . 76 18 jbe XCrackMe.004018D3
004018BB > A1 00414000 mov eax,dword ptr ds:[0x404100]
004018C0 . 8B0D 04414000 mov ecx,dword ptr ds:[0x404104]
004018C6 . A3 F8404000 mov dword ptr ds:[0x4040F8],eax
004018CB . 890D FC404000 mov dword ptr ds:[0x4040FC],ecx
004018D1 . EB 12 jmp XCrackMe.004018E5
004018D3 > 68 F0404000 push CrackMe.004040F0 ; /pPerformanceFreq = CrackMe.004040F0
004018D8 . FF15 08304000 call dword ptr ds:[<&KERNEL32.QueryPerformanceFrequency>] ; \QueryPerformanceFrequency[color=#333333][font=arial][size=13px]:返回硬件支持的高精度计数器的频率 说白了就是检测调试器用的[/size][/font][/color]
004018DE . 68 F8404000 push CrackMe.004040F8
004018E3 . FFD6 call esi
004018E5 > 6A 64 push 0x64 ; /Timeout = 100. ms
004018E7 . FF15 04304000 call dword ptr ds:[<&KERNEL32.Sleep>] ; \Sleep
004018ED . 68 00414000 push CrackMe.00404100
004018F2 . FFD6 call esi
004018F4 . 8B15 00414000 mov edx,dword ptr ds:[0x404100]
004018FA . A1 F8404000 mov eax,dword ptr ds:[0x4040F8]
004018FF . 8B35 FC404000 mov esi,dword ptr ds:[0x4040FC]
00401905 . 2BD0 sub edx,eax
00401907 . A1 04414000 mov eax,dword ptr ds:[0x404104]
0040190C . 6A 00 push 0x0
0040190E . 1BC6 sbb eax,esi
00401910 . 68 E8030000 push 0x3E8
00401915 . 50 push eax
00401916 . 52 push edx
00401917 . E8 94050000 call CrackMe.00401EB0
0040191C . 8B0D F4404000 mov ecx,dword ptr ds:[0x4040F4]
00401922 . 51 push ecx
00401923 . 8B0D F0404000 mov ecx,dword ptr ds:[0x4040F0]
00401929 . 51 push ecx
0040192A . 52 push edx
0040192B . 50 push eax
0040192C . E8 CF040000 call CrackMe.00401E00
00401931 . 3D D0070000 cmp eax,0x7D0
00401936 . 5E pop esi ; 监视调试器的一样方法
00401937 EB 05 jmp XCrackMe.0040193E ; 爆破这里
00401939 . E8 22FFFFFF call CrackMe.00401860 ; 退出
0040193E > C2 1000 retn 0x10
下面为另一个TIMER过程 也有大量的检测CC [C++] 纯文本查看 复制代码 00401A71 . 51 push ecx ; /Text
00401A72 . 52 push edx ; |hWnd
00401A73 . FF15 F4314000 call dword ptr ds:[<&USER32.SetWindowTextA>] ; \SetWindowTextA
00401A79 . 8D4424 48 lea eax,dword ptr ss:[esp+0x48]
00401A7D . C74424 48 3F0>mov dword ptr ss:[esp+0x48],0x1003F
00401A85 . 50 push eax ; /pContext
00401A86 . FF15 14304000 call dword ptr ds:[<&KERNEL32.GetCurrentThread>] ; |[GetCurrentThread
00401A8C . 50 push eax ; |hThread
00401A8D . FF15 10304000 call dword ptr ds:[<&KERNEL32.GetThreadContext>] ; \GetThreadContext
00401A93 . 395C24 4C cmp dword ptr ss:[esp+0x4C],ebx ; 又是一种检测调试的方法
00401A97 . 75 12 jnz XCrackMe.00401AAB ; 这里可以NOP JNZ 失败 也可以将后面的退出函数NOP掉
00401A99 . 395C24 50 cmp dword ptr ss:[esp+0x50],ebx
00401A9D . 75 0C jnz XCrackMe.00401AAB
00401A9F . 395C24 54 cmp dword ptr ss:[esp+0x54],ebx
00401AA3 . 75 06 jnz XCrackMe.00401AAB
00401AA5 . 395C24 58 cmp dword ptr ss:[esp+0x58],ebx
00401AA9 . 74 05 je XCrackMe.00401AB0
00401AAB 90 nop ; 退出
00401AAC 90 nop ; nop掉
00401AAD 90 nop
00401AAE 90 nop
00401AAF 90 nop
00401AB0 > 8B35 20304000 mov esi,dword ptr ds:[<&KERNEL32.LoadLibraryA>] ; kernel32.LoadLibraryA
00401AB6 . 8D4C24 20 lea ecx,dword ptr ss:[esp+0x20]
00401ABA . 8D5424 0C lea edx,dword ptr ss:[esp+0xC]
00401ABE . 51 push ecx ; /ProcNameOrOrdinal
00401ABF . 52 push edx ; |/FileName
00401AC0 . FFD6 call esi ; |\LoadLibraryA
00401AC2 . 8B3D 00304000 mov edi,dword ptr ds:[<&KERNEL32.GetProcAddress>] ; |kernel32.7C80AE30
00401AC8 . 50 push eax ; |hModule
00401AC9 . FFD7 call edi ; \GetProcAddress
00401ACB . 6A 14 push 0x14
00401ACD . 50 push eax
00401ACE . E8 9DFDFFFF call CrackMe.00401870 ; 再次检测是否对SetTimer下断点
00401AD3 . 83C4 08 add esp,0x8
00401AD6 . 85C0 test eax,eax
00401AD8 EB 05 jmp XCrackMe.00401ADF ; 直接JMP
00401ADA . E8 81FDFFFF call CrackMe.00401860 ; 退出
00401ADF > 8D4424 2C lea eax,dword ptr ss:[esp+0x2C]
00401AE3 . 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
00401AE7 . 50 push eax
00401AE8 . 51 push ecx
00401AE9 . FFD6 call esi
00401AEB . 50 push eax
00401AEC . FFD7 call edi ; 得到KillTimer地址
00401AEE . 6A 14 push 0x14
00401AF0 . 50 push eax
00401AF1 . E8 7AFDFFFF call CrackMe.00401870 ; 检测是否对KillTimer下断点
00401AF6 . 83C4 08 add esp,0x8
00401AF9 . 85C0 test eax,eax
00401AFB EB 05 jmp XCrackMe.00401B02 ; 直接JMP
00401AFD . E8 5EFDFFFF call CrackMe.00401860
00401B02 > 8D5424 38 lea edx,dword ptr ss:[esp+0x38]
00401B06 . 8D4424 0C lea eax,dword ptr ss:[esp+0xC]
00401B0A . 52 push edx
00401B0B . 50 push eax
00401B0C . FFD6 call esi
00401B0E . 50 push eax
00401B0F . FFD7 call edi ; 得到"SetWindowTextA"地址
00401B11 . 6A 14 push 0x14
00401B13 . 50 push eax
00401B14 . E8 57FDFFFF call CrackMe.00401870 ; 检测是否对SetWindowTextA下断点
00401B19 . 83C4 08 add esp,0x8
00401B1C . 85C0 test eax,eax
00401B1E . 5F pop edi
00401B1F . 5E pop esi
00401B20 . 5B pop ebx
00401B21 EB 05 jmp XCrackMe.00401B28 ; 直接JMP
00401B23 . E8 38FDFFFF call CrackMe.00401860
00401B28 > 68 56020000 push 0x256
00401B2D . 68 10154000 push CrackMe.00401510 ; 入口地址
00401B32 . E8 39FDFFFF call CrackMe.00401870 ; 检测入口点是否下CC断点
00401B37 . 83C4 08 add esp,0x8
00401B3A . 85C0 test eax,eax
00401B3C EB 05 jmp XCrackMe.00401B43 ; 直接JMP
00401B3E . E8 1DFDFFFF call CrackMe.00401860
00401B43 > 6A 0B push 0xB
00401B45 . 68 68174000 push CrackMe.00401768
00401B4A . E8 21FDFFFF call CrackMe.00401870 ; 对代码中间一个地方检测CC
00401B4F . 83C4 08 add esp,0x8
00401B52 . 85C0 test eax,eax
00401B54 EB 05 jmp XCrackMe.00401B5B ; 直接JMP
00401B56 . E8 05FDFFFF call CrackMe.00401860
00401B5B > 68 CD000000 push 0xCD
00401B60 . 68 75174000 push CrackMe.00401775
00401B65 . E8 06FDFFFF call CrackMe.00401870 ; 对代码中间一个地方检测CC
00401B6A . 83C4 08 add esp,0x8
00401B6D . 85C0 test eax,eax
00401B6F EB 05 jmp XCrackMe.00401B76 ; 直接JMP
00401B71 . E8 EAFCFFFF call CrackMe.00401860
00401B76 > 81C4 08030000 add esp,0x308
00401B7C . C2 1000 retn 0x10
接下来 下断点 GetWindowTextA 解决了上面的退出代码就可以下断点进行调试了 输入 abcdef 123456 错误 下面来到 将下面的验证X 处全部NOP掉即可完成爆破 因为是CrackMe 我就不分析加密过程了 直接爆破
[C++] 纯文本查看 复制代码 00401666 . 8B65 E8 mov esp,dword ptr ss:[ebp-0x18]
00401669 . 8B85 C4FEFFFF mov eax,dword ptr ss:[ebp-0x13C]
0040166F . 8B48 64 mov ecx,dword ptr ds:[eax+0x64]
00401672 . 898D D0FEFFFF mov dword ptr ss:[ebp-0x130],ecx
00401678 . 8B95 D0FEFFFF mov edx,dword ptr ss:[ebp-0x130]
0040167E . 8995 BCFEFFFF mov dword ptr ss:[ebp-0x144],edx
00401684 . 8D85 E4FEFFFF lea eax,dword ptr ss:[ebp-0x11C]
0040168A . 8985 B8FEFFFF mov dword ptr ss:[ebp-0x148],eax
00401690 > 8B8D B8FEFFFF mov ecx,dword ptr ss:[ebp-0x148]
00401696 . 8A11 mov dl,byte ptr ds:[ecx]
00401698 . 8895 B7FEFFFF mov byte ptr ss:[ebp-0x149],dl
0040169E . 8B85 BCFEFFFF mov eax,dword ptr ss:[ebp-0x144]
004016A4 . 3A10 cmp dl,byte ptr ds:[eax] ; 这里是最后跳到这里 同学们先看后面的分析,最后SEH调回来 进行的最后验证
004016A6 . 75 46 jnz XCrackMe2.004016EE ; 验证3 直接NOP掉
004016A8 . 80BD B7FEFFFF>cmp byte ptr ss:[ebp-0x149],0x0 ; 这里有点难理解 大家可以调试看看就明白了
004016AF . 74 31 je XCrackMe2.004016E2
004016B1 . 8B8D B8FEFFFF mov ecx,dword ptr ss:[ebp-0x148]
004016B7 . 8A51 01 mov dl,byte ptr ds:[ecx+0x1]
004016BA . 8895 B6FEFFFF mov byte ptr ss:[ebp-0x14A],dl
004016C0 . 8B85 BCFEFFFF mov eax,dword ptr ss:[ebp-0x144]
004016C6 . 3A50 01 cmp dl,byte ptr ds:[eax+0x1]
004016C9 . 75 23 jnz XCrackMe2.004016EE ; 验证4 直接NOP掉
004016CB . 8385 B8FEFFFF>add dword ptr ss:[ebp-0x148],0x2
004016D2 . 8385 BCFEFFFF>add dword ptr ss:[ebp-0x144],0x2
004016D9 . 80BD B6FEFFFF>cmp byte ptr ss:[ebp-0x14A],0x0
004016E0 .^ 75 AE jnz XCrackMe2.00401690
004016E2 > C785 B0FEFFFF>mov dword ptr ss:[ebp-0x150],0x0
004016EC . EB 0B jmp XCrackMe2.004016F9
004016EE > 1BC9 sbb ecx,ecx
004016F0 . 83D9 FF sbb ecx,-0x1
004016F3 . 898D B0FEFFFF mov dword ptr ss:[ebp-0x150],ecx
004016F9 > 8B95 B0FEFFFF mov edx,dword ptr ss:[ebp-0x150]
004016FF . 8995 ACFEFFFF mov dword ptr ss:[ebp-0x154],edx
00401705 . 83BD ACFEFFFF>cmp dword ptr ss:[ebp-0x154],0x0
0040170C . 75 1E jnz XCrackMe2.0040172C
0040170E . 8D85 D8FEFFFF lea eax,dword ptr ss:[ebp-0x128]
00401714 . 50 push eax
00401715 . 68 EA030000 push 0x3EA
0040171A . 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
00401720 . E8 79060000 call <jmp.&MFC42.#3092>
00401725 . 8BC8 mov ecx,eax
00401727 . E8 6C060000 call <jmp.&MFC42.#6199> ; 这里是设置成功标志
0040172C > C745 FC FFFFF>mov dword ptr ss:[ebp-0x4],-0x1
00401733 . E9 FA000000 jmp CrackMe2.00401832
00401738 > E8 23010000 call CrackMe2.00401860
0040173D . E9 F0000000 jmp CrackMe2.00401832
00401742 > 6A 01 push 0x1
00401744 . 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
0040174A . E8 43060000 call <jmp.&MFC42.#6334>
0040174F . 6A 00 push 0x0
00401751 . 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
00401757 . E8 36060000 call <jmp.&MFC42.#6334>
0040175C . 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
00401762 . 8B51 60 mov edx,dword ptr ds:[ecx+0x60]
00401765 . 8995 CCFEFFFF mov dword ptr ss:[ebp-0x134],edx
0040176B . 8D85 E4FEFFFF lea eax,dword ptr ss:[ebp-0x11C]
00401771 . 50 push eax
00401772 . 8B8D CCFEFFFF mov ecx,dword ptr ss:[ebp-0x134]
00401778 . 51 push ecx
00401779 . E8 92FDFFFF call CrackMe2.00401510 ; 根据用户名得到密码
0040177E . 83C4 08 add esp,0x8 ; 在这里可以看到堆栈中有正确的密码
00401781 . 8B95 C4FEFFFF mov edx,dword ptr ss:[ebp-0x13C]
00401787 . 8B42 64 mov eax,dword ptr ds:[edx+0x64]
0040178A . 8985 C8FEFFFF mov dword ptr ss:[ebp-0x138],eax
00401790 . 8B8D C8FEFFFF mov ecx,dword ptr ss:[ebp-0x138]
00401796 . 898D A8FEFFFF mov dword ptr ss:[ebp-0x158],ecx
0040179C . 8D95 E4FEFFFF lea edx,dword ptr ss:[ebp-0x11C]
004017A2 . 8995 A4FEFFFF mov dword ptr ss:[ebp-0x15C],edx
004017A8 > 8B85 A4FEFFFF mov eax,dword ptr ss:[ebp-0x15C]
004017AE . 8A08 mov cl,byte ptr ds:[eax]
004017B0 . 888D A3FEFFFF mov byte ptr ss:[ebp-0x15D],cl
004017B6 . 8B95 A8FEFFFF mov edx,dword ptr ss:[ebp-0x158]
004017BC . 3A0A cmp cl,byte ptr ds:[edx]
004017BE . 75 46 jnz XCrackMe2.00401806 ; 验证1 直接NOP掉
004017C0 . 80BD A3FEFFFF>cmp byte ptr ss:[ebp-0x15D],0x0
004017C7 . 74 31 je XCrackMe2.004017FA
004017C9 . 8B85 A4FEFFFF mov eax,dword ptr ss:[ebp-0x15C]
004017CF . 8A48 01 mov cl,byte ptr ds:[eax+0x1]
004017D2 . 888D A2FEFFFF mov byte ptr ss:[ebp-0x15E],cl
004017D8 . 8B95 A8FEFFFF mov edx,dword ptr ss:[ebp-0x158]
004017DE . 3A4A 01 cmp cl,byte ptr ds:[edx+0x1]
004017E1 . 75 23 jnz XCrackMe2.00401806 ; 验证2 直接NOP掉
004017E3 . 8385 A4FEFFFF>add dword ptr ss:[ebp-0x15C],0x2
004017EA . 8385 A8FEFFFF>add dword ptr ss:[ebp-0x158],0x2
004017F1 . 80BD A2FEFFFF>cmp byte ptr ss:[ebp-0x15E],0x0
004017F8 .^ 75 AE jnz XCrackMe2.004017A8
004017FA > C785 9CFEFFFF>mov dword ptr ss:[ebp-0x164],0x0
00401804 . EB 0B jmp XCrackMe2.00401811
00401806 > 1BC0 sbb eax,eax
00401808 . 83D8 FF sbb eax,-0x1
0040180B . 8985 9CFEFFFF mov dword ptr ss:[ebp-0x164],eax
00401811 > 8B8D 9CFEFFFF mov ecx,dword ptr ss:[ebp-0x164]
00401817 . 898D 98FEFFFF mov dword ptr ss:[ebp-0x168],ecx
0040181D . 83BD 98FEFFFF>cmp dword ptr ss:[ebp-0x168],0x0
00401824 . 75 07 jnz XCrackMe2.0040182D ;这里不跳
00401826 .^ E9 11FEFFFF jmp CrackMe2.0040163C ; 这里调向上面的SEH 进入SEH最后再进入上面的验证3
0040182B . EB 05 jmp XCrackMe2.00401832
0040182D >^ E9 06FFFFFF jmp CrackMe2.00401738 ; 调向失败
00401832 > 8B4D F0 mov ecx,dword ptr ss:[ebp-0x10]
00401835 . 64:890D 00000>mov dword ptr fs:[0],ecx
0040183C . 5F pop edi
0040183D . 5E pop esi
0040183E . 5B pop ebx
0040183F . 8BE5 mov esp,ebp
00401841 . 5D pop ebp
00401842 . C3 retn
分析道这里就完毕了
|