首页
社区
课程
招聘
[原创]每日一破解(第5天 CM测试等级破解) 江湖将会有我的传说
发表于: 2012-8-6 21:06 14724

[原创]每日一破解(第5天 CM测试等级破解) 江湖将会有我的传说

2012-8-6 21:06
14724

[软件名称]: CRECKME 0 CRECKME 0 程序和分析源码.zip
[应用平台]:Win9X/NT/2000/XP
[软件大小]:8K
[破解声明]:为了检验自己的逆向破解能力,请求斑竹给个邀请码,鼓励我继续写下去。顺便感谢一下党,感谢国家,感谢我们家的曾曾。
[破解工具]:PEiD,IDA 5.5,PE Explore
[备注] 破解软件来源于看雪论坛中的帖子 (本人原创CRACKME系列 难度由0--9,看你属于哪一级)
[作者]:INightElf
[破解日期]:2012-08-06
前言:
   之前一段时间都在破解MASM32 / TASM32之类的软件,由于比较简单,很快就无法引起我的兴趣,在看雪论坛闲逛,发现有网友发(原创CRACKME系列 难度由0--9,看你属于哪一级)帖子,该破解软件由MFC 编译的,刚好用来检验本人掌握的MFC原理是否扎实,也来检验自己的破解水平。
言归正传!下面开始我们的破解之旅

1.查壳,用PEid 检测,编译器为编译器Microsoft Visual C++ 7.0 Method2 [调试],无壳。


2.用PE Explore 查看软件的资源,如图。可见该软件有三个对话框,其中编号为129的对话框为主要窗口, 验证输入的Name 和Serial是否正确。请记下Name控件的ID 为1000,Serial 控件的ID 为1001,确定按钮控件ID为1,取消按钮ID 为2。当输入的Name和Serial 正确,则弹出编号为102的对话框。编号为100则是关于对话框.请记下上面描述的ID号。
这是为了后面的反汇编代码中处理按钮消息做准备,请注意这里的ID 号是10进制



3.用IDA 反汇编CrackMe0,得到CrackMe0反汇编清单,熟悉MFC编程的人都知道,一般程序都会把初始化放到CXXXApp::InitInstance和CXXXApp::IInitApplication 这两个函数,而CXXXApp则继承了CWinApp,并在CXXXApp::InitInstance 中调用父类的CWinApp::InitInstance,在CXXXApp:: IInitApplication 中调用父类的CWinApp:: IInitApplication。所以逆向的一步,则是找到CWinApp::InitInstance和CWinApp:: IInitApplication这两个函数,然后通过交叉引用注释,查找到CXXXApp::InitInstance和CWinApp:: IInitApplication函数所在地址。



由于IDA强大的反汇编库函数,只要对Function Name 列表进行排序,很容易就找到了,在CrackMe0函数中,程序的初始化放到CXXXApp::InitInstance中。导航到交叉引用函数sub_401090,该函数就是CXXXApp::InitInstance。并对该函数进行重命名为CXXXWinApp::InitInstance。


4.在CXXXWinApp::InitInstance函数中仔细观察,看到了地址0x004010EE 调用了CDialog::DoModal(void),表明在该地址前面创建了对话框。在text:004010DA行有一个Call 函数指令,表明了该函数创建了对话框
.text:004010EE call?DoModal@CDialog@@UAEHXZ ; CDialog::DoModal(void)
导航进去该函数查看。果然验证了之前的推测. .text:004014CE 地址的ID为129,根据步骤2的ID比较,可以断定创建的窗口为即将破解的主窗口, 其中CrackMeMainDialogVirtualFunctionTable为主窗口的虚函数表
.text:004014EC   mov     dword ptr [esi], offset CrackMeMainDialogVirtualFunctionTable ; 虚函数表格
CrackMeMainDialogVirtualFunctionTable 函数名为本人重新命名的,请注意。为什么在这里要特别强调主窗口的虚函数表呢?这是非常关键的一步。猜猜!嘻嘻。
当当当……….谜底是(为了获取确定按钮的消息处理函数) 。是不是觉得我很无聊呢。



.text:004014B0 CreateCrackMeMainDialog proc near       ; CODE XREF: CXXXWinApp::InitInstance(void)+4A p
.text:004014B0
.text:004014B0 var_10          = dword ptr -10h
.text:004014B0 var_C           = dword ptr -0Ch
.text:004014B0 var_4           = dword ptr -4
.text:004014B0 arg_0           = dword ptr  4
.text:004014B0
.text:004014B0                 push    0FFFFFFFFh
.text:004014B2                 push    offset SEH_4014B0
.text:004014B7                 mov     eax, large fs:0
.text:004014BD                 push    eax
.text:004014BE                 mov     large fs:0, esp
.text:004014C5                 push    ecx
.text:004014C6                 mov     eax, [esp+10h+arg_0]
.text:004014CA                 push    esi
.text:004014CB                 push    eax
.text:004014CC                 mov     esi, ecx
.text:004014CE                 push    129             ; hDlgTemplateId 对话框模板ID,在这里也是破解的主窗口
.text:004014D3                 mov     [esp+1Ch+var_10], esi
.text:004014D7                 call    ??0CDialog@@QAE@IPAVCWnd@@@Z ; CDialog::CDialog(uint,CWnd *)
.text:004014DC                 push    offset unk_403940
.text:004014E1                 lea     ecx, [esi+74h]
.text:004014E4                 mov     [esp+18h+var_4], 0
.text:004014EC                 mov     dword ptr [esi], offset CrackMeMainDialogVirtualFunctionTable ; 虚函数表格
.text:004014F2                 call    ds:??0?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@QAE@PBD@Z ; ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(char const *)
.text:004014F8                 mov     ecx, [esp+14h+var_C]
.text:004014FC                 mov     dword ptr [esi+78h], 0
.text:00401503                 mov     eax, esi
.text:00401505                 pop     esi
.text:00401506                 mov     large fs:0, ecx
.text:0040150D                 add     esp, 10h
.text:00401510                 retn    4
.text:00401510 CreateCrackMeMainDialog endp

5.导航到CrackMeMainDialogVirtualFunctionTable 虚函数表格。
在地址
.rdata:0040380C dd offset ?GetTypeLib@CCmdTarget@@UAEJKPAPAUITypeLib@@@Z ; CCmdTarget::GetTypeLib(ulong,ITypeLib * *)
和地址
.rdata:00403814 dd offset ?GetCommandMap@CCmdTarget@@MBEPBUAFX_OLECMDMAP@@XZ ; CCmdTarget::GetCommandMap(void)
之间的函数就是主窗口消息栈区函数。请注意该函数已经被本人重新命名过。
.rdata:00403810                 dd offset j_?GetMessageMap@CrackMeMainDialog@@MBEPBUAFX_MSGMAP@@XZ ; CrackMeMainDialog::GetMessageMap(void)


6.导航到CrackMeMainDialog::GetMessageMap(void) 函数,在该函数里面的地址.text:00401545 设置断点,并执行程序。
text:00401540 ; protected: virtual struct AFX_MSGMAP const * __thiscall CrackMeMainDialog::GetMessageMap(void)const
.text:00401540 j_?GetMessageMap@CrackMeMainDialog@@MBEPBUAFX_MSGMAP@@XZ proc near
.text:00401540                 mov     eax, offset off_403780
.text:00401545                 retn
.text:00401545 j_?GetMessageMap@CrackMeMainDialog@@MBEPBUAFX_MSGMAP@@XZ endp
则程序中断在地址text:00401545,查看此时的EAX寄存器值,[EAX+4] == 0x00403784 的值就是MFC 对话框的消息处理函数列表。



在栈区Jump到地址0x00403784



在栈区Jump到地址0x00403788


在这里必须说明以下MFC消息处理函数的结构,定义如下
#define ON_CONTROL(wNotifyCode, id, memberFxn) \
        { WM_COMMAND, (WORD)wNotifyCode, (WORD)id, (WORD)id, AfxSigCmd_v, \
                (static_cast< AFX_PMSG > (memberFxn)) },

#define WM_COMMAND     0x0111  发送命令消息,一般控件按钮消息都是通过这个命令发送的。
Id 就是按钮的ID号, memberFxn 就是按钮的消息处理函数。
从上图和步骤二可以知道,确定按钮的ID号为1,所以地址0x004015A0 为确定按钮的消息处理函数。本人把该函数重新命名为BtnOK

7.        十万长征终于完成了一半,导航到函数地址,剩下的工作就是分析算法了。
.text:004015A0 ; 确定按钮事件
.text:004015A0
.text:004015A0 BtnOK           proc near
.text:004015A0
.text:004015A0 ; FUNCTION CHUNK AT .text:004015D5 SIZE 00000034 BYTES
.text:004015A0
.text:004015A0                 push    esi
.text:004015A1                 push    edi
.text:004015A2                 push    1
.text:004015A4                 mov     esi, ecx
.text:004015A6                 call    ?UpdateData@CWnd@@QAEHH@Z ; CWnd::UpdateData(int)
.text:004015AB                 lea     edi, [esi+74h]  ; 获取Name 字段的内容
.text:004015AE                 mov     ecx, edi
.text:004015B0                 call    ds:?GetLength@?$CSimpleStringT@D$00@ATL@@QBEHXZ ; ATL::CSimpleStringT<char,1>::GetLength(void)
.text:004015B6                 cmp     eax, 6          ; name 字段的字符串的长度必须大于等于6
.text:004015B9                 jge     short loc_4015D5
.text:004015BB                 cmp     dword ptr [esi+78h], 186A0h
.text:004015C2                 jge     short loc_4015D5
.text:004015C4                 push    0               ; unsigned int
.text:004015C6                 push    0               ; unsigned int
.text:004015C8                 push    offset aNameOrSerialIs ; "Name or Serial is too short!"
.text:004015CD                 call    ?AfxMessageBox@@YGHPBDII@Z ; AfxMessageBox(char const *,uint,uint)
.text:004015D2
.text:004015D2 loc_4015D2:
.text:004015D2                 pop     edi
.text:004015D3                 pop     esi
.text:004015D4                 retn
.text:004015D4 BtnOK           endp
.text:004015D4
.text:004015D5 ; ---------------------------------------------------------------------------
.text:004015D5 ; START OF FUNCTION CHUNK FOR BtnOK
.text:004015D5
.text:004015D5 loc_4015D5:                             ; Name 字段的内容与"IndolentAfternoon" 字符串比较,
.text:004015D5                 push    offset aIndolentaftern ; 一致则继续比较Serial,从这里就说明了Name 必须=='IndolentAfternoon'
.text:004015DA                 mov     ecx, edi
.text:004015DC                 call    ds:?Compare@?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@QBEHPBD@Z ; ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Compare(char const *)
.text:004015E2                 test    eax, eax
.text:004015E4                 jnz     short loc_4015D2
.text:004015E6                 cmp     dword ptr [esi+78h], 5687255 ; 获取Serial 字符串与5687255 常量比较,一致则说明了输入的Serial
.text:004015E6                                         ; 是正确的,并给出成功的提示符,证明了 Serial  ==5687255
.text:004015ED                 jnz     short loc_4015D2
.text:004015EF                 push    0               ; unsigned int
.text:004015F1                 push    0               ; unsigned int
.text:004015F3                 push    offset aCongratulation ; "Congratulation! Correct Serial Num,do n"...
.text:004015F8                 call    ?AfxMessageBox@@YGHPBDII@Z ; AfxMessageBox(char const *,uint,uint)
.text:004015FD                 mov     eax, [esi]
.text:004015FF                 pop     edi
.text:00401600                 mov     ecx, esi
.text:00401602                 pop     esi
.text:00401603                 jmp     dword ptr [eax+154h]
.text:00401603 ; END OF FUNCTION CHUNK FOR BtnOK

8.前面分析了那么多步骤只是为了获取按钮消息事件而已,感觉有点学院派的作风,其实可以用很多简单的方法来获取。但是就无法理解MFC消息处理机制了。总结前面的步骤
第1步获取: CWinApp::InitInstance函数地址
第2步获取: CXXXWinApp::InitInstance函数地址
第3步获取: 主对话框的虚函数表CrackMeMainDialogVirtualFunctionTable
第4步获取: 主对话框的CrackMeMainDialog::GetMessageMap(void)const 函数
第5步获取: 获取确定按钮事件.text:004015A0  BtnOK
很多MFC程序都可以用前面的5个步骤来获取按钮的消息,这个是本人总结出来的宝贵经验,现在无偿奉献给大家。明天把算法的步骤补上,其实该算法特别简单。但是写到现在我已经没有精力写下去了。累!

9.算法太简单了,在BtnOK函数中直接给出明文比较,通过分析可以得出 Name ==” IndolentAfternoon” ,Serial == 5687255   不需要注册机。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (50)
雪    币: 353
活跃值: (516)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
2
请各位指教指教!
2012-8-7 09:05
0
雪    币: 42
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
菜菜前来学习,表示不会用ida,只会用od
2012-8-8 21:50
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持一下,用IDA确实要多练习。
2012-8-9 10:03
0
雪    币: 353
活跃值: (516)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
5
OD和IDA都要会啊,这样进步才会快
2012-8-9 11:12
0
雪    币: 62
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
每天就只能挤出一小时来学习破解。Mark一下,学习。
2012-8-9 15:46
0
雪    币: 353
活跃值: (516)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
7
努力努力!
2012-8-9 20:34
0
雪    币: 39
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
我这里有一款软件,不知道能不能破解,有兴趣请联系QQ8895428
2012-8-9 20:55
0
雪    币: 39
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
mark支持支持学习了
2012-9-23 19:05
0
雪    币: 104
活跃值: (27)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
不懂的路过,技术的一定要顶!
2012-9-24 19:09
0
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
看了好久 还是不知道  看来 还要努力
2012-9-25 14:41
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
慢慢学习,mark一下……
2012-9-25 15:11
0
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
还是不会,支持下
2012-9-28 21:28
0
雪    币: 0
活跃值: (85)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
正在努力向楼主看齐中~
2012-9-29 12:31
0
雪    币: 210
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
学习正在努力
2012-9-30 13:32
0
雪    币: 32
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
这里有辆宝马给你开开http://www.ncwnkj.com/
2012-10-5 01:45
0
雪    币: 353
活跃值: (516)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
17
宝马?其实这篇文章最主要的是熟悉mfc 框架.要不然真的看不懂
2012-11-6 10:58
0
雪    币: 9
活跃值: (57)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
18
你对IDA这么熟悉啊。佩服啊,我这么多年会员了都一直在潜水,嘻嘻
2012-11-6 11:37
0
雪    币: 85
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
在学习之路上。。。
2012-11-6 12:50
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
菜鸟表示看不懂。。但有一天我会看明白的,加油!!
2012-11-6 17:01
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
看一下 我要多多练习
2012-11-6 17:29
0
雪    币: 36
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习一下  呼呼  大神
2012-11-6 18:32
0
雪    币: 353
活跃值: (516)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
23
汗啊,我什么时候成为成为大神啦。
2012-11-6 21:11
0
雪    币: 25
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
好吧  我也看不明白  但是也在努力中
2012-11-8 12:23
0
雪    币: 91
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
在OD中调试分析要比在IDA中简单得多,关键代码很容易跟踪出来。
0-3,我都搞过了,算法简单,4用到了md5加密,只能爆破
5之后就用到了vm了,没搞了。
2012-12-25 21:37
0
游客
登录 | 注册 方可回帖
返回
//