本帖最后由 JoyChou 于 2013-12-19 14:20 编辑
作者:JoyChou
博客:http://joychou.sinaapp.com
日期:2013年12月16日
这个CM是VC6.0写的MFC程序。这次我就不用MFC按钮入口工具,试试手动来找找。
在Xp下可以这样:
首先用IDA找到CCmdTarget::OnCmdMsg函数的地址,这个CM是00401C6C
OD中,来到00401C6C这个地址,是一个jmp xxxx, enter进入,再向下翻,在push [eax+0x14]下断,此时[eax+0x14]等于0x7DD491F4,
其实这个就是按钮的入口地址,只是有的时候会单步两步才能到处下断。单步两步后,来到入口点00401580
一来就构造了一个SEH的handler,先留意点,下面肯定有异常发生
[AppleScript] 纯文本查看 复制代码 00401580 . 55 push ebp
00401581 . 8BEC mov ebp,esp
00401583 . 6A FF push -0x1
00401585 . 68 10344000 push CrackMe.00403410
0040158A . 68 F01D4000 push <jmp.&MSVCRT._except_handler3> ; SE Hander; SE 处理程序安装
0040158F . 64:A1 0000000>mov eax,dword ptr fs:[0] ; fs:[0]
00401595 . 50 push eax
00401596 . 64:8925 00000>mov dword ptr fs:[0],esp
0040159D . 81C4 A8FEFFFF add esp,-0x158
接着
[AppleScript] 纯文本查看 复制代码 00401742 > \6A 01 push 0x1
00401744 . 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
0040174A . E8 43060000 call <jmp.&MFC42.#CWnd::UpdateData_6334> ; 获取用户名
0040174F . 6A 00 push 0x0
00401751 . 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
00401757 . E8 36060000 call <jmp.&MFC42.#CWnd::UpdateData_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 CrackMe.00401510 ; 算法,此时,看堆栈,密文出来了
0040177E . 83C4 08 add esp,0x8
堆栈
[AppleScript] 纯文本查看 复制代码 0018F650 00362DD0 ASCII "JoyChou"
0018F654 0018F6B0 ASCII "6FA6B5649CA6AF"
算法很简单,不是重点,就不写keygen了。
做到这其实这题已经差不多算做完了。不过,如果这只是我们想要的结果,那么分析还有什么意思呢?
接着继续看……
重新来一次,输入正确的一组用户名和密码,看看程序的总体流程。
一路单步,看到异常处
[AppleScript] 纯文本查看 复制代码 0040163C C745 FC 0000000>mov dword ptr ss:[ebp-0x4],0x0
00401643 8A15 00000000 mov dl,byte ptr ds:[0] ; 访问0异常
00401649 8815 00000000 mov byte ptr ds:[0],dl
0040164F E8 0C020000 call CrackMe.00401860
这个时候在按钮入口的0040158A push 0x401DF0的0x401DF0处下断
一路单步到7523DD32处F7
[AppleScript] 纯文本查看 复制代码 7523DD28 33DB xor ebx,ebx
7523DD2A 33C9 xor ecx,ecx
7523DD2C 33D2 xor edx,edx
7523DD2E 33F6 xor esi,esi
7523DD30 33FF xor edi,edi
7523DD32 FFD0 call eax ; F7
最后就可以看到成功的样子了,利用SetWindowTextA设置静态文本框为“破解成功”
[AppleScript] 纯文本查看 复制代码 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.#CWnd::GetDlgItem_3092>
00401725 8BC8 mov ecx,eax
00401727 E8 6C060000 call <jmp.&MFC42.#CWnd::SetWindowTextA_6199>
0040172C C745 FC FFFFFFF>mov dword ptr ss:[ebp-0x4],-0x1
上面就算基本了解程序流程,不过此CM还有几个地方值得学习。
0x1. 在MFC的OnInitDialog里面检测SetTimer函数的int断点,以及作者自己定义的函数int3 断点
call CrackMe.00401870 这个call就是检测int 3断点
[AppleScript] 纯文本查看 复制代码 00401870 55 push ebp
00401871 8BEC mov ebp,esp
00401873 51 push ecx
00401874 57 push edi
00401875 C745 FC 0000000>mov dword ptr ss:[ebp-0x4],0x0
0040187C FC cld
0040187D 8B7D 08 mov edi,dword ptr ss:[ebp+0x8]
00401880 8B4D 0C mov ecx,dword ptr ss:[ebp+0xC]
00401883 B0 CC mov al,0xCC
00401885 F2:AE repne scas byte ptr es:[edi]
00401887 75 07 jnz XCrackMe.00401890
00401889 C745 FC 0100000>mov dword ptr ss:[ebp-0x4],0x1
00401890 8B45 FC mov eax,dword ptr ss:[ebp-0x4]
00401893 5F pop edi
00401894 8BE5 mov esp,ebp
00401896 5D pop ebp
00401897 C3 retn
0x2. 进程退出,都是利用call 00401860退出
分析的时候把这个call retn掉,这样程序就不会退出了。
[AppleScript] 纯文本查看 复制代码
7C92E510 > 8BD4 mov edx,esp
7C92E512 0F34 sysenter
7C92E514 > C3 retn
0x3. 在SetTimer的回调函数里检测硬件断点,检测到就退出
[AppleScript] 纯文本查看 复制代码 00401A68 33C0 xor eax,eax
00401A6A 8B50 20 mov edx,dword ptr ds:[eax+0x20]
00401A6D 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]
00401A71 51 push ecx
00401A72 52 push edx
00401A73 FF15 F4314000 call dword ptr ds:[<&USER32.SetWindowTextA>] ; USER32.SetWindowTextA
00401A79 8D4424 48 lea eax,dword ptr ss:[esp+0x48]
00401A7D C74424 48 3F000>mov dword ptr ss:[esp+0x48],0x1003F
00401A85 50 push eax
00401A86 FF15 14304000 call dword ptr ds:[<&KERNEL32.GetCurrentThread>] ; kernel32.GetCurrentThread
00401A8C 50 push eax
00401A8D FF15 10304000 call dword ptr ds:[<&KERNEL32.GetThreadContext>] ; kernel32.Wow64GetThreadContext
00401A93 395C24 4C cmp dword ptr ss:[esp+0x4C],ebx
00401A97 75 12 jnz XCrackMe.00401AAB
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
0x4. 利用QueryPerformanceCounter计算程序执行时间,大于2S就退出,达到反调试。
[AppleScript] 纯文本查看 复制代码 004018A0 . A1 FC404000 mov eax,dword ptr ds:[0x4040FC]
004018A5 . 56 push esi
004018A6 . 8B35 0C304000 mov esi,dword ptr ds:[<&KERNEL32.QueryPe>; kernel32.QueryPerformanceCounter
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.QueryPerfo>; \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:[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 ; 判断事件是否小于2秒,大于就退出
00401936 . 5E pop esi
00401937 . 7E 05 jle XCrackMe-.0040193E
00401939 . E8 22FFFFFF call CrackMe-.00401860
0040193E > C2 1000 retn 0x10
成功截图
|