【吾爱2013CM大赛解答】--CrackMe -- 苏紫方璇 BY zcc1414爆破分析
本帖最后由 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 00383D50ASCII "abcdef"
0012F73C 0012F798ASCII "919394969799"
总结:
程序设置两个TIMER过程 对各个函数进行CC检测防止对函数进行下断点
程序用了几种防调试的办法
验证时用到了SEH异常跳转去到另外地点验证这种方法值得提倡
运行程序修改代码就会退出发现有TIMER过程
发现有线索了timer但是程序退出了回溯代码找到下面这些发现设置了两个TIEMR过程下面的检测断点是都是检测 CC断点
下面的检测断点是检测 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:
004013E3 .8BC8 mov ecx,eax
004013E5 .FF52 7C call dword ptr ds:
004013E8 .EB 02 jmp XCrackMe.004013EC
004013EA >33C0 xor eax,eax
004013EC >8B40 20 mov eax,dword ptr ds:
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:
0040140F .8BC8 mov ecx,eax
00401411 .FF52 7C call dword ptr ds:
00401414 .EB 02 jmp XCrackMe.00401418
00401416 >33C0 xor eax,eax
00401418 >8B40 20 mov eax,dword ptr ds:
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回调函数
004018A0 .A1 FC404000 mov eax,dword ptr ds: ;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:
004018B7 .85C0 test eax,eax
004018B9 .76 18 jbe XCrackMe.004018D3
004018BB >A1 00414000 mov eax,dword ptr ds:
004018C0 .8B0D 04414000 mov ecx,dword ptr ds:
004018C6 .A3 F8404000 mov dword ptr ds:,eax
004018CB .890D FC404000 mov dword ptr ds:,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:返回硬件支持的高精度计数器的频率 说白了就是检测调试器用的
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:
004018FA .A1 F8404000 mov eax,dword ptr ds:
004018FF .8B35 FC404000 mov esi,dword ptr ds:
00401905 .2BD0 sub edx,eax
00401907 .A1 04414000 mov eax,dword ptr ds:
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:
00401922 .51 push ecx
00401923 .8B0D F0404000 mov ecx,dword ptr ds:
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 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:
00401A7D .C74424 48 3F0>mov dword ptr ss:,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:,ebx ;又是一种检测调试的方法
00401A97 .75 12 jnz XCrackMe.00401AAB ; 这里可以NOP JNZ 失败也可以将后面的退出函数NOP掉
00401A99 .395C24 50 cmp dword ptr ss:,ebx
00401A9D .75 0C jnz XCrackMe.00401AAB
00401A9F .395C24 54 cmp dword ptr ss:,ebx
00401AA3 .75 06 jnz XCrackMe.00401AAB
00401AA5 .395C24 58 cmp dword ptr ss:,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:
00401ABA .8D5424 0C lea edx,dword ptr ss:
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:
00401AE3 .8D4C24 0C lea ecx,dword ptr ss:
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:
00401B06 .8D4424 0C lea eax,dword ptr ss:
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我就不分析加密过程了直接爆破
00401666 .8B65 E8 mov esp,dword ptr ss:
00401669 .8B85 C4FEFFFF mov eax,dword ptr ss:
0040166F .8B48 64 mov ecx,dword ptr ds:
00401672 .898D D0FEFFFF mov dword ptr ss:,ecx
00401678 .8B95 D0FEFFFF mov edx,dword ptr ss:
0040167E .8995 BCFEFFFF mov dword ptr ss:,edx
00401684 .8D85 E4FEFFFF lea eax,dword ptr ss:
0040168A .8985 B8FEFFFF mov dword ptr ss:,eax
00401690 >8B8D B8FEFFFF mov ecx,dword ptr ss:
00401696 .8A11 mov dl,byte ptr ds:
00401698 .8895 B7FEFFFF mov byte ptr ss:,dl
0040169E .8B85 BCFEFFFF mov eax,dword ptr ss:
004016A4 .3A10 cmp dl,byte ptr ds: ;这里是最后跳到这里 同学们先看后面的分析,最后SEH调回来 进行的最后验证
004016A6 .75 46 jnz XCrackMe2.004016EE ;验证3 直接NOP掉
004016A8 .80BD B7FEFFFF>cmp byte ptr ss:,0x0 ;这里有点难理解大家可以调试看看就明白了
004016AF .74 31 je XCrackMe2.004016E2
004016B1 .8B8D B8FEFFFF mov ecx,dword ptr ss:
004016B7 .8A51 01 mov dl,byte ptr ds:
004016BA .8895 B6FEFFFF mov byte ptr ss:,dl
004016C0 .8B85 BCFEFFFF mov eax,dword ptr ss:
004016C6 .3A50 01 cmp dl,byte ptr ds:
004016C9 .75 23 jnz XCrackMe2.004016EE ;验证4直接NOP掉
004016CB .8385 B8FEFFFF>add dword ptr ss:,0x2
004016D2 .8385 BCFEFFFF>add dword ptr ss:,0x2
004016D9 .80BD B6FEFFFF>cmp byte ptr ss:,0x0
004016E0 .^ 75 AE jnz XCrackMe2.00401690
004016E2 >C785 B0FEFFFF>mov dword ptr ss:,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:,ecx
004016F9 >8B95 B0FEFFFF mov edx,dword ptr ss:
004016FF .8995 ACFEFFFF mov dword ptr ss:,edx
00401705 .83BD ACFEFFFF>cmp dword ptr ss:,0x0
0040170C .75 1E jnz XCrackMe2.0040172C
0040170E .8D85 D8FEFFFF lea eax,dword ptr ss:
00401714 .50 push eax
00401715 .68 EA030000 push 0x3EA
0040171A .8B8D C4FEFFFF mov ecx,dword ptr ss:
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:,-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:
0040174A .E8 43060000 call <jmp.&MFC42.#6334>
0040174F .6A 00 push 0x0
00401751 .8B8D C4FEFFFF mov ecx,dword ptr ss:
00401757 .E8 36060000 call <jmp.&MFC42.#6334>
0040175C .8B8D C4FEFFFF mov ecx,dword ptr ss:
00401762 .8B51 60 mov edx,dword ptr ds:
00401765 .8995 CCFEFFFF mov dword ptr ss:,edx
0040176B .8D85 E4FEFFFF lea eax,dword ptr ss:
00401771 .50 push eax
00401772 .8B8D CCFEFFFF mov ecx,dword ptr ss:
00401778 .51 push ecx
00401779 .E8 92FDFFFF call CrackMe2.00401510 ;根据用户名得到密码
0040177E .83C4 08 add esp,0x8 ;在这里可以看到堆栈中有正确的密码
00401781 .8B95 C4FEFFFF mov edx,dword ptr ss:
00401787 .8B42 64 mov eax,dword ptr ds:
0040178A .8985 C8FEFFFF mov dword ptr ss:,eax
00401790 .8B8D C8FEFFFF mov ecx,dword ptr ss:
00401796 .898D A8FEFFFF mov dword ptr ss:,ecx
0040179C .8D95 E4FEFFFF lea edx,dword ptr ss:
004017A2 .8995 A4FEFFFF mov dword ptr ss:,edx
004017A8 >8B85 A4FEFFFF mov eax,dword ptr ss:
004017AE .8A08 mov cl,byte ptr ds:
004017B0 .888D A3FEFFFF mov byte ptr ss:,cl
004017B6 .8B95 A8FEFFFF mov edx,dword ptr ss:
004017BC .3A0A cmp cl,byte ptr ds:
004017BE .75 46 jnz XCrackMe2.00401806 ;验证1 直接NOP掉
004017C0 .80BD A3FEFFFF>cmp byte ptr ss:,0x0
004017C7 .74 31 je XCrackMe2.004017FA
004017C9 .8B85 A4FEFFFF mov eax,dword ptr ss:
004017CF .8A48 01 mov cl,byte ptr ds:
004017D2 .888D A2FEFFFF mov byte ptr ss:,cl
004017D8 .8B95 A8FEFFFF mov edx,dword ptr ss:
004017DE .3A4A 01 cmp cl,byte ptr ds:
004017E1 .75 23 jnz XCrackMe2.00401806 ;验证2直接NOP掉
004017E3 .8385 A4FEFFFF>add dword ptr ss:,0x2
004017EA .8385 A8FEFFFF>add dword ptr ss:,0x2
004017F1 .80BD A2FEFFFF>cmp byte ptr ss:,0x0
004017F8 .^ 75 AE jnz XCrackMe2.004017A8
004017FA >C785 9CFEFFFF>mov dword ptr ss:,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:,eax
00401811 >8B8D 9CFEFFFF mov ecx,dword ptr ss:
00401817 .898D 98FEFFFF mov dword ptr ss:,ecx
0040181D .83BD 98FEFFFF>cmp dword ptr ss:,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:
00401835 .64:890D 00000>mov dword ptr fs:,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
分析道这里就完毕了
{:1_928:}来个有码的, 好思路,感谢大牛的分析! 好好学习下,这方面我是一窍不通.
页:
[1]