本帖最后由 Thend 于 2013-12-15 16:27 编辑
[文章标题]: 【吾爱2013CM大赛解答】--CrackMe -- 苏紫方璇 简单分析+注册机编写
[作者信息]: 0n1y3nd
[操作平台]: Win7 Sp1 & Windows XP Sp3
[使用工具]: OD
[软件名称]: CrackMe -- 苏紫方璇
[下载地址]: 【吾爱2013CM大赛题目】-- CrackMe -- 苏紫方璇 http://www.52pojie.cn/thread-228417-1-1.html
正文:
查壳,程序无壳,是用MFC写的。
直接运行下,什么都不输入,点击确定,提示注册成功,这可能是一个小bug,作者没考虑周全吧。随便输入点,点确定后程序直接退出。
直接载入OD:
下BP GetWindowTextA断点和BP ExitProcess断点,为什么下这个断点呢?因为下 BP GetDlgItemTextA断点无效。
F9几次运行程序,随便输入,断在了GetWindowTextA这个函数那里。
堆栈窗口:
0012F6BC 73D45CD8 /CALL 到 GetWindowTextA 来自 mfc42.73D45CD2
0012F6C0 00020368 |hWnd = 00020368 (class='Edit',parent=00030364)
0012F6C4 00393A68 |Buffer = 00393A68
0012F6C8 00000009 \Count = 0x9
0012F6CC 0012F708
0012F6D0 0012FE8C
0012F6D4 /0012F734
0012F6D8 |004012A7 返回到 CrackMe.004012A7 来自 <jmp.&MFC42.#2370>
跟随到004012A7来。
[C] 纯文本查看 复制代码 0040129B 50 push eax
0040129C 68 E8030000 push 0x3E8
004012A1 57 push edi
004012A2 E8 C70A0000 call <jmp.&MFC42.#2370> ; 获取文本框内容
004012A7 83C6 64 add esi,0x64
004012AA 56 push esi
004012AB 68 E9030000 push 0x3E9
004012B0 57 push edi
004012B1 E8 B80A0000 call <jmp.&MFC42.#2370> ; 同上
004012B6 5F pop edi
004012B7 5E pop esi
004012B8 C2 0400 retn 0x4
返回一次后到了mfc42这个模块中,继续执行到用户代码:
返回到这里:
[AppleScript] 纯文本查看 复制代码 00401742 6A 01 push 0x1
00401744 8B8D C4FEFFFF mov ecx,dword ptr ss:[ebp-0x13C]
0040174A E8 43060000 call <jmp.&MFC42.#6334> ; 获取文本内容call
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 CrackMe.00401510 ; 这个call很明显就是算法call
0040177E 83C4 08 add esp,0x8
往下看:
果然,下面是一系列的比较和跳转。
[AppleScript] 纯文本查看 复制代码 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 short CrackMe.00401806
004017C0 80BD A3FEFFFF 0>cmp byte ptr ss:[ebp-0x15D],0x0
004017C7 74 31 je short CrackMe.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 short CrackMe.00401806
004017E3 8385 A4FEFFFF 0>add dword ptr ss:[ebp-0x15C],0x2
004017EA 8385 A8FEFFFF 0>add dword ptr ss:[ebp-0x158],0x2
004017F1 80BD A2FEFFFF 0>cmp byte ptr ss:[ebp-0x15E],0x0
004017F8 ^ 75 AE jnz short CrackMe.004017A8
004017FA C785 9CFEFFFF 0>mov dword ptr ss:[ebp-0x164],0x0
00401804 EB 0B jmp short CrackMe.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 0>cmp dword ptr ss:[ebp-0x168],0x0
00401824 75 07 jnz short CrackMe.0040182D
00401826 ^ E9 11FEFFFF jmp CrackMe.0040163C
0040182B EB 05 jmp short CrackMe.00401832
0040182D ^ E9 06FFFFFF jmp CrackMe.00401738
00401832 8B4D F0 mov ecx,dword ptr ss:[ebp-0x10]
00401835 64:890D 0000000>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
进入算法call:
关键代码:
[AppleScript] 纯文本查看 复制代码 0040154A 8B7424 20 mov esi,dword ptr ss:[esp+0x20] ; 算法开始
0040154E 8BF9 mov edi,ecx
00401550 33C0 xor eax,eax
00401552 8A03 mov al,byte ptr ds:[ebx] ; 存入eax
00401554 8D0440 lea eax,dword ptr ds:[eax+eax*2] ; eax的值 * 3
00401557 99 cdq
00401558 2BC2 sub eax,edx
0040155A D1F8 sar eax,1 ; eax的值右移 1 位
0040155C 25 FF000000 and eax,0xFF ; and 0xFF 其实就是取eax中的低两位
00401561 50 push eax
00401562 8D4424 14 lea eax,dword ptr ss:[esp+0x14]
00401566 50 push eax
00401567 56 push esi
00401568 FFD5 call ebp ; 格式化
0040156A 83C4 0C add esp,0xC
0040156D 83C6 02 add esi,0x2
00401570 43 inc ebx
00401571 4F dec edi
00401572 ^ 75 DC jnz short CrackMe.00401550
算法很简单,只对用户名做处理。
再看后面的验证:
验证就不多说了,就是用户名用算法计算出一串字符串,逐位和注册码比较。全部成功则通过。
算法:
用户名的每一位的ASSII码 * 3 然后右移1位,最后和 0XFF 与运算。
注册机关键代码:
[C] 纯文本查看 复制代码 for (i=0;i<nameLength;i++) //循环对每一位进行处理
{
kkk=(int)name[i];
[/i] kkk = kkk * 3;
kkk = kkk >> 1;
kkk = kkk & 0xFF;
printf("%02x",kkk);
}
提供一组:
0n1y3nd
48A549B54CA596
注册机:
好吧,多说一点:这个程序有反调试功能。设置的那个退出比较有趣。
检测到程序在被调试之后,就马上调用一个call
[AppleScript] 纯文本查看 复制代码 00401860 6A 00 push 0x0 ; 退出的暗桩
00401862 |. 6A FF push -0x1
00401864 |. E8 E7FFFFFF call CrackMe.00401850 ; 跟进
00401869 \. C3 retn
继续跟进:
[AppleScript] 纯文本查看 复制代码 00401850 /$ B8 01010000 mov eax,0x101
00401855 |. BA 0003FE7F mov edx,0x7FFE0300 ; ntdll的地址
0040185A |. 3E:FF12 call dword ptr ds:[edx] ; 跟进
0040185D \. C2 0800 retn 0x8
call dword ptr ds:[edx] 就是调用:KiFastSystemCall这个函数
看下这个函数到底干什么:
[AppleScript] 纯文本查看 复制代码 7C92E4F0 > 8BD4 mov edx,esp
7C92E4F2 0F34 sysenter
7C92E4F4 > C3 retn
R3下的API调用最终都需要进入内核,Win32则是通过int 0x2e进入内核态,此切换过程通过KiFastSystemCall调用,KiFastSystemCall即通过sysenter快速系统调用进入内核执行,然后内核态执行完成内核系统服务后退出,降落点位于KiFastSystemCallRet,此时表示内核已经执行完成了,返回用户态。
所以在能够直接退出,这也是下一些退出的API断点无效的原因。
|