-
-
[原创]菜鸟试手crackme
-
发表于:
2011-9-29 14:32
5432
-
在『CrackMe◇ReverseMe』版面看到一个帖子http://http://bbs.pediy.com/showthread.php?t=140109,决定试试如何进行crack,下面是自己的过程,高手飘过
使用工具
windbg idapro
首先打开程序,是一个简单的窗口,一个输入框,一个ok按钮
在输入框里面随便输入一些数字,然后点击ok,发现程序退出消失了,那我们就从捕获ok这个按钮消息来入手吧
使用windbg载入程序,F5继续运行下去,出现窗口,使用spy+++工具,获取ok窗口的句柄
然后在windbg中中断程序运行,输入命令
bp USER32!TranslateMessage "j dwo(dwo(@esp+4))=002E01B8 & dwo(dwo(@esp+4)+4)=202 '' ; 'gc'"
命令的意思是对USER32!TranslateMessage 系统api设置断点,因为改函数是消息分发的核心函数(当然其他消息分发的函数也可以)
该函数的原型是
BOOL WINAPI TranslateMessage(
__in const MSG *lpMsg
);
其第一个参数就是一个消息指针,而消息的结构是
typedef struct tagMSG
{
HWND hwnd ;
UINT message ;
WPARAM wParam ;
LPARAM lParam ;
DWORD time ;
POINT pt ;
}
MSG, * PMSG ;
因此,这里dwo(dwo(@esp+4))=002E01B8 & dwo(dwo(@esp+4)+4)=202 指的是
第一个参数(esp+4)存放的是msg的指针,因此dwo(@esp+4)是改指针值,然后该指针值指向的是消息结构,所以dwo(dwo(@esp+4))就是消息结构的第一个成员,即处理消息的窗口句柄,而dwo(dwo(@esp+4)+4)就是消息类型
因而,改命令的整个意思,就是当窗口句柄为ok(002E01B8 ,看spy++的图)这个button的时候,并且消息类型是202(WM_LBUTTONUP)时,中断,而其他情况下不中断,其实就是用windbg实现了消息中断,然后F5继续运行起来
在输入框中输入fuckyou(系统中不太可能出现的字符,当然我的有些不雅……),然后用鼠标点击OK键(必须用鼠标点击,不能直接用回车键,因为我们只断了鼠标的消息)
这样,当点击OK键后,windbg就会中断到我们的位置来
eax=00000001 ebx=00000002 ecx=00631748 edx=7c92e401 esi=00432810 edi=00631748
eip=77d18bf6 esp=0012fd38 ebp=0012fd58 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
USER32!TranslateMessage:
77d18bf6 8bff mov edi,edi
输入命令kv查看一下栈的情况
ChildEBP RetAddr Args to Child
0012fd34 77d274f9 00432810 00432810 00432818 USER32!TranslateMessage (FPO: [1,0,0])
0012fd58 77d3c6d3 0035019c 0067ae90 00432810 USER32!IsDialogMessageW+0x36f (FPO: [2,3,0])
0012fd78 0041dc9b 0035019c 00432810 0012fe40 USER32!IsDialogMessageA+0xfd (FPO: [2,1,4])
WARNING: Stack unwind information not available. Following frames may be wrong.
0012fd88 0041d6a4 00432810 0041a9bf 00432810 image00400000+0x1dc9b
0012febc 00421b37 0000000e 001660a0 00434814 image00400000+0x1d6a4
0012fedc 00421cc8 00000003 001660c8 004327e0 image00400000+0x21b37
0012ffc0 7c817067 010df6f2 010df726 7ffde000 image00400000+0x21cc8
0012fff0 00000000 0040ab8d 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])
然后shift+f11跳槽系统api,一直运行到程序自己的代码中
eax=00000001 ebx=77d2aeab ecx=00000000 edx=00000000 esi=0012fe40 edi=00432810
eip=0041dc9b esp=0012fd88 ebp=00432810 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
image00400000+0x1dc9b:
0041dc9b 5e pop esi
单步走几步看看
同时结合idapro,发现这里好像并没有特别的处理,那么应该校验的地方并不在这里,那么我们就去内存中找找我们刚才输入的字符串
s -a 0 Lffffff "fuckyou" (范围设置大一些)
0:000> s -a 0 lffffff "fuckyou"
00943990 66 75 63 6b 79 6f 75 00-0d f0 ad ba 0d f0 ad ba fuckyou.........
可以看到字串存放的地址是00943990
于是对该地址下硬件访问断点
ba r1 00943990
然后F5运行
0:000> ba r1 00943990
0:000> g
Breakpoint 1 hit
eax=00000066 ebx=ffffffff ecx=0012ff08 edx=7c92e4f4 esi=004327e0 edi=00943990
eip=0040a6e9 esp=0012fe20 ebp=0012ffc0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
image00400000+0xa6e9:
0040a6e9 8b0d68f24200 mov ecx,dword ptr [image00400000+0x2f268 (0042f268)] ds:0023:0042f268=0042f272
看到代码来到了image00400000+0xa6e9:处
于是去IDAPro看看能否有啥新发现
G到地址0040a6e9处
.text:0040A6C5 ; __int64 __cdecl _atoi64(const char *String)
.text:0040A6C5 __atoi64 proc near ; CODE XREF: sub_401EF0+68p
.text:0040A6C5
.text:0040A6C5 var_4 = dword ptr -4
.text:0040A6C5 String = dword ptr 4
.text:0040A6C5
.text:0040A6C5 push ecx
.text:0040A6C6 push ebx
.text:0040A6C7 push ebp
.text:0040A6C8 push esi
.text:0040A6C9 push edi
.text:0040A6CA mov edi, [esp+14h+String]
.text:0040A6CE
.text:0040A6CE loc_40A6CE: ; CODE XREF: __atoi64+35j
.text:0040A6CE cmp dword_42F474, 1
.text:0040A6D5 jle short loc_40A6E6
.text:0040A6D7 movzx eax, byte ptr [edi]
.text:0040A6DA push 8 ; Type
.text:0040A6DC push eax ; C
.text:0040A6DD call __isctype
.text:0040A6E2 pop ecx
.text:0040A6E3 pop ecx
.text:0040A6E4 jmp short loc_40A6F5
.text:0040A6E6 ; ---------------------------------------------------------------------------
.text:0040A6E6
.text:0040A6E6 loc_40A6E6: ; CODE XREF: __atoi64+10j
.text:0040A6E6 movzx eax, byte ptr [edi]
.text:0040A6E9 mov ecx, dword ptr byte_42F268
.text:0040A6EF mov al, [ecx+eax*2]
.text:0040A6F2 and eax, 8
.text:0040A6F5
.text:0040A6F5 loc_40A6F5: ; CODE XREF: __atoi64+1Fj
.text:0040A6F5 test eax, eax
.text:0040A6F7 jz short loc_40A6FC
.text:0040A6F9 inc edi
.text:0040A6FA jmp short loc_40A6CE
.text:0040A6FC ; ---------------------------------------------------------------------------
.text:0040A6FC
....................
可以看到是系统api __atoi64在引用,于是直接跳到调用改系统函数的地方sub_401EF0+68地方
.text:00401F53 loc_401F53: ; CODE XREF: sub_401EF0+51j
.text:00401F53 mov eax, [esp+0D8h+String]
.text:00401F57 push eax ; String
.text:00401F58 call __atoi64
.text:00401F5D add esp, 4
.text:00401F60 cmp eax, 417981B2h
.text:00401F65 jnz short loc_401F6C
.text:00401F67 cmp edx, 3
.text:00401F6A jz short loc_401F79
.text:00401F6C
.text:00401F6C loc_401F6C: ; CODE XREF: sub_401EF0+75j
.text:00401F6C mov [esp+0D8h+var_4], 2
.text:00401F77 jmp short loc_401FE0
有两处关键比对代码
可以看到,是那edx eax组成的64位数(__atoi64返回的结果)与数字3417981b2进行对比,于是讲3417981b2转换成10进制
13983383986
于是尝试输入该号码到输入框,ok,通过……
呵呵,该CM比较简单,很适合新手上路,这里没有对windbg和idapro的操作进行详细说明,不懂的可以参考windbg的帮助文档和论坛大神们的帖子,呵呵,第一次,高兴ing:)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)