160个CrackMe之108 mfc程序 寻找按钮事件,代码还原(下)

网友投稿 983 2022-09-16

160个CrackMe之108 mfc程序 寻找按钮事件,代码还原(下)

160个CrackMe之108 mfc程序 寻找按钮事件,代码还原(下)

·分析该CrackMe按钮事件

这个check就是个按钮,现在用visual studio提供的工具看看这个按钮id

·选择自己的Spy++(不会用的话百度查一下)

找到check按钮id是1

·那该程序的检查按钮事件就为AFX_MSGMAP_ENTRY 按钮;按钮。nMessage = WM_COMMAND ; 按钮。nCode = BN_CLICKED ; 按钮。nID = 1 ; 按钮。nLastID = 1 ; 按钮。nSig = AfxSigCmd_v ; 按钮。pfn =未知;

等价替换后 btn.nMessage=0x0111; btn.nCode=0; btn.nID=1; btn.nLastID=1; btn.nSig=AfxSigCmd_v; btn.pfn=CMFCApplication3Dlg::未知;

btn的内存呈现形式为 nMessage,nCode,nID,nLastID,nSig,pfn 可以不用管nSig,pfn的值,只用搜索前四项就够了,等价替换为 0x0111, 0, 1,1,nSig,pfn 等价替换为 11 01 00 00, 00 00 00 00, 01 00 00 00, 01 00 00 00 ,nSig,pfn 等价替换为 11 01 00 00 00 00 00 00 01 00 00 00 01 00 00 00 找到按钮事件地址 795E7980

·地址795E7980的汇编代码看着有点怪异的是因为这里是虚函数调用(vcall) 执行到795E798D jmp eax f7跟进去后来到真正的按钮事件地址

·现在来讲讲vcall,写了个小例子#include #include class myclass { public: virtual void func1() {

} virtual void func2() { }

}; int main ( ) { printf ( "MYACLS::myvirfunc1()地址=%p\n" , & myclass :: func1 ) ; //打印的是vcall函数 printf ( "MYACLS::myvirfunc2()地址=%p\n" , & myclass :: func2 ) ; myclass * pmyobj = new myclass ( ) ;

返回 1 ;

} ·执行的结果

而myvirfunc1 myvirfunc2函数真正的地址为

现在00FB1084与00FB1088代码组合

是不是和地址795E7980代码很相似

·vcall 的作用调整这个指针到真正的虚函数中

·现在看看代码还原ida打开该程序跳转00401512

text:00401518 mov [ebp+var_20], ecx .text:0040151B mov ax, word_40315C .text:00401521 mov word ptr [ebp+String], ax .text:00401525 xor ecx, ecx .text:00401527 mov [ebp+var_A], ecx .text:0040152A mov [ebp+var_6], ecx .text:0040152D mov edx, dword_403020 .text:00401533 mov dword ptr [ebp+String2], edx .text:00401536 mov eax, dword_403024 .text:0040153B mov [ebp+var_18], eax .text:0040153E mov cx, word_403028 .text:00401545 mov [ebp+var_14], cx

var_20看前后使用是 用来this指针的不用管

var_A和var_6都被初始化为0,上下文都没有使用,说明是数组 String 只初始化了2个字节,加上var_A和var_6,String是10个字节

String2 和var_18,var_14地址相连,var_18,var_14上下文都没有使用,说明是数组 var_14只初始化了2个字节,加上String2和var_18,String2是10个字节 dword_403020 值为4472423C,dword_403024值为426F532D,word_403028值为003E换成asci码为

代码为 CHAR String[10]={0};//因为汇编代码中都数组中的值被初始化为0了,所以写成String[10]={0} CHAR String2[10]=""; .text:00401549 push 0Ah ; int .text:0040154B lea edx, [ebp+String].text:0040154E push edx ; char * .text:0040154F push 3E8h ; int .text:00401554 mov ecx, [ebp+var_20] ; this .text:00401557 call ?GetDlgItemTextA@CWnd@@QBEHHPADH@Z ; CWnd::GetDlgItemTex.text:0040155C lea eax, [ebp+String].text:0040155F push eax ; lpString .text:00401560 call ds:lstrlenA .text:00401566 mov [ebp+var_10], eax .text:00401569 cmp [ebp+var_10], 1 .text:0040156D jnb short loc_401585

push的是10,调用的函数是intGetDlgItemText(intnID**,LPTSTRlpStr,intnMaxCount),说明数组 大就是10, var_10=lstrlenA函数的返回值, 后比较的后的跳转指令是jnb 说明var_10是无符号的

代码为 GetDlgItemTextA(1000, String, 10); unsigned int var_10; var_10 = lstrlenA(String); if ( var_10<1).text:0040156F push 40h ; '@' ; unsigned int .text:00401571 push offset aCrackme ; "CrackMe" .text:00401576 push offset aEnterRegistrat ; "Enter Registration Number" .text:0040157B mov ecx, [ebp+var_20] ; this .text:0040157E call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char .text:00401583 jmp short loc_4015C1 .text:00401585 ; --------------------------------------------------------------------------- .text:00401585 .text:00401585 loc_401585: ; CODE XREF: sub_401512+5B↑j .text:00401585 lea ecx, [ebp+String2] .text:00401588 push ecx ; lpString2 .text:00401589 lea edx, [ebp+String] .text:0040158C push edx ; lpString1 .text:0040158D call ds:lstrcmpA .text:00401593 test eax, eax .text:00401595 jnz short loc_4015AD .text:00401597 push 40h ; '@' ; unsigned int .text:00401599 push offset aCrackme_0 ; "CrackMe" .text:0040159E push offset aCorrectWayToGo ; "Correct way to go!!" .text:004015A3 mov ecx, [ebp+var_20] ; this .text:004015A6 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char .text:004015AB jmp short loc_4015C1 .text:004015AD ; --------------------------------------------------------------------------- .text:004015AD .text:004015AD loc_4015AD: ; CODE XREF: sub_401512+83↑j .text:004015AD push 40h ; '@' ; unsigned int .text:004015AF push offset aCrackme_1 ; "CrackMe" .text:004015B4 push offset aIncorrectTryAg ; "Incorrect try again!!" .text:004015B9 mov ecx, [ebp+var_20] ; this .text:004015BC call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char .text:004015C1 .text:004015C1 loc_4015C1: ; CODE XREF: sub_401512+71↑j .text:004015C1 ; sub_401512+99↑j .text:004015C1 mov esp, ebp .text:004015C3 pop ebp .text:004015C4 retn .text:004015C4 sub_401512 endp

汇编结构来看感觉是 if, elseif, else结构代码为 MessageBoxA("Enter Registration Number", "CrackMe", 0x40u); else if ( lstrcmpA(String, String2) ) MessageBoxA("Incorrect try again!!", "CrackMe", 0x40u); else MessageBoxA("Correct way to go!!", "CrackMe", 0x40u);

CHAR String2[10]=""; unsigned int var_10; CHAR String[10]={0};//因为汇编代码中都数组中的值被初始化为0了,所以写成String[10]={0} GetDlgItemTextA(1000, String, 10); var_10 = lstrlenA(String); if ( var_10<1) MessageBoxA("Enter Registration Number", "CrackMe", 0x40u); else if ( lstrcmpA(String, String2) ) MessageBoxA("Incorrect try again!!", "CrackMe", 0x40u); else MessageBoxA("Correct way to go!!", "CrackMe", 0x40u);

·因为该程序是vc6写的,我自己也用vc6写了一份,因为该crackme引用的dll是 MFC42.DLL 明说不是Debug编译的,Debug编译的是用的MFC42D.DLL,所以选择用Release编译,第二因为该crackme是用ebp寻找的局部变量,说明没有开 o2优化编译,我个人就选择的无优化编译,最后生成的二进制和原版还有略有差异

·最后输入秘钥 实现破解

·完成自己代码还原的mfc程序以打包到附件了

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:反射简介及简单应用(简单反射是什么的反射)
下一篇:免费开源的录屏软件Captura使用、安装、配置
相关文章

 发表评论

暂时没有评论,来抢沙发吧~