轻量级前端框架助力开发者提升项目效率与性能
983
2022-09-16
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
} 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]="
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]="
·因为该程序是vc6写的,我自己也用vc6写了一份,因为该crackme引用的dll是 MFC42.DLL 明说不是Debug编译的,Debug编译的是用的MFC42D.DLL,所以选择用Release编译,第二因为该crackme是用ebp寻找的局部变量,说明没有开 o2优化编译,我个人就选择的无优化编译,最后生成的二进制和原版还有略有差异
·最后输入秘钥 实现破解
·完成自己代码还原的mfc程序以打包到附件了
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~