【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
http://bbs.pediy.com/showthread.php?t=82660
【详细过程】
本文所讲的方法,其实是一个很古老的方法了。以前,考虑到此法的杀伤力巨大,不便于公布。
随着软件开发者保护意识的提高和软件保护技术的发展,此法的杀伤力逐渐下降成为普通等级。
我本人这学期的课程和任务十分多,打算暂时把程序调试这个业余爱好放一放,估计至少会有半年时间不常来看雪了。
把这个方法写出来,算是给大家的告别礼物。
对于直接使用SDK而不使用第三方库的程序,我们要定位到程序的“关键代码”并不困难。通常在CreateWindow函数或 DialogBoxParam函数下断点,可以直接获得其主界面的窗口过程或对话框过程。但是对于使用了MFC的程序,我们找到的窗口过程或对话框过程是 在MFC提供的程序框架的内部,经过层层的分发和筛选,消息才最终到达用户代码,直接分析起来比较繁琐。
幸好,有一个Olly的脚本,可以直接帮助我们找到诸如OnOK()之类的函数。这个脚本用到的方法,是建立在对MFC内部机制充分理解的基础上,通过在消息分发的代码处下条件断点而完成的。
然而,我马上要讲到的这个方法,在一定程度上,比这个脚本还好使,可以一下就定位到我们感兴趣的代码处。而且,可以举一反三,如果你看明白了其中的思路,可以自己扩展成为十分强大的“必杀技”,不仅对MFC,对其它的应用程序框架也有效果。
我就不讲我如何想到的这个方法,只讲两个例子。如果你看懂了这个例子,其中的思路肯定会明白了。而且,十分简单。
我以MFC42为例。先打开VC6,创建一个MFC的对话框程序,按默认设置。我们在“OK”按钮的处理函数OnOK()的开头,写上这样一句:
__asm int 3
然后,按Release编译。
现在,用OD调试程序,不要忽略int3异常,F9运行,点击“OK”,OD马上断下。
看堆栈:
0012F80C 73EFE938 返回到 MFC42.73EFE938 0012F810 00000000 0012F814 004022E8 MFCDialo.004022E8
我们到 MFC42.73EFE938这看一下:
73EFE932 8B4D 08 MOV ECX, DWORD PTR SS:[EBP+8] 73EFE935 FF55 14 CALL DWORD PTR SS:[EBP+14] ; 这句就是调用用户函数的CALL 73EFE938 5F POP EDI ; 这就是堆栈中的 MFC42.73EFE938 73EFE939 8BC6 MOV EAX, ESI ...
我们看到,73EFE935处的CALL [EBP+14]的目标函数就是我们的OnOK()。记住这个地址。
我们按ALT+E,打开模块列表,双击下面MFC42.dll这一行:
Executable modules 基址 大小 入口 名称 文件版本 路径 00400000 00005000 00401780 MFCSigna 1, 0, 0, 1 F:\Documents\MY CODE\MFCDialog\Release\MFCDialog.exe 00460000 0009B000 00486E23 ADVAPI32 5.2.3790.3959 (s D:\WINDOWS\syswow64\ADVAPI32.dll 00500000 0008B000 0050155C OLEAUT32 5.2.3790.4202 D:\WINDOWS\syswow64\OLEAUT32.dll 00590000 00052000 005A006D SHLWAPI 6.00.3790.3959 ( D:\WINDOWS\syswow64\SHLWAPI.dll 02160000 00017000 odbcint 3.526.1830.0 (sr D:\WINDOWS\system32\odbcint.dll 48890000 0003D000 488C5681 ODBC32 3.526.3959.0 (sr D:\WINDOWS\system32\ODBC32.dll 4B3C0000 00050000 4B3C1574 MSCTF 5.2.3790.3959 (s D:\WINDOWS\SysWOW64\MSCTF.dll 4DC30000 0002E000 4DC49F69 msctfime 5.2.3790.3959 (s D:\WINDOWS\system32\msctfime.ime 71BB0000 00009000 71BB1060 WSOCK32 5.2.3790.0 (srv0 D:\WINDOWS\system32\WSOCK32.dll 71BF0000 00008000 71BF123D WS2HELP 5.2.3790.1830 (s D:\WINDOWS\system32\WS2HELP.dll 71C00000 00017000 71C02560 WS2_32 5.2.3790.3959 (s D:\WINDOWS\system32\WS2_32.dll 73EB0000 00121000 73F84A8E MFC42 6.06.8063.0 D:\WINDOWS\system32\MFC42.DLL 75490000 00065000 754C93CA USP10 1.0422.3790.3959 D:\WINDOWS\system32\USP10.dll 75E60000 00027000 75E61239 apphelp 5.2.3790.3959 (s D:\WINDOWS\system32\apphelp.dll 76190000 00012000 76193341 MSASN1 5.2.3790.3959 (s D:\WINDOWS\syswow64\MSASN1.dll 761B0000 00093000 761B15FA CRYPT32 5.131.3790.3959 D:\WINDOWS\syswow64\CRYPT32.dll 762B0000 00049000 762B16A5 comdlg32 6.00.3790.3959 ( D:\WINDOWS\syswow64\comdlg32.dll 77210000 000AB000 772115A2 WININET 6.00.3790.4392 ( D:\WINDOWS\syswow64\WININET.dll 77530000 00097000 775948BA COMCTL32 5.82 (srv03_sp2_ D:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.3790.3959_x-ww_78FCF8D0\COMCTL32.dll 77670000 00139000 776BC692 ole32 5.2.3790.3959 (s D:\WINDOWS\syswow64\ole32.dll 77BA0000 0005A000 77BAF78B msvcrt 7.0.3790.3959 (s D:\WINDOWS\syswow64\msvcrt.dll 7C8D0000 007FF000 7C92BB2B SHELL32 6.00.3790.4184 ( D:\WINDOWS\syswow64\SHELL32.dll 7D4C0000 00130000 7D4DFD59 kernel32 5.2.3790.4062 (s D:\WINDOWS\syswow64\kernel32.dll 7D600000 000F0000 ntdll 5.2.3790.3959 (s D:\WINDOWS\system32\ntdll.dll 7D800000 00090000 7D82B710 GDI32 5.2.3790.4396 (s D:\WINDOWS\syswow64\GDI32.dll 7D8D0000 00050000 7D8E0E4B Secur32 5.2.3790.3959 (s D:\WINDOWS\syswow64\Secur32.dll 7D930000 000D0000 7D969635 USER32 5.2.3790.4033 (s D:\WINDOWS\syswow64\USER32.dll 7DA20000 000E0000 7DA3049E RPCRT4 5.2.3790.4115 (s D:\WINDOWS\syswow64\RPCRT4.dll 7DBC0000 00009000 7DBC12E2 LPK 5.2.3790.3959 (s D:\WINDOWS\system32\LPK.DLL 7DBD0000 00103000 7DC5A99E comctl_1 6.0 (srv03_sp2_r D:\WINDOWS\WinSxS\WOW64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.3790.3959_x-ww_5FA17F4E\comctl32.dll 7DEE0000 00060000 7DEF02D0 IMM32 5.2.3790.3959 (s D:\WINDOWS\system32\IMM32.DLL 7DF50000 00070000 7DF637D7 uxtheme 6.00.3790.3959 ( D:\WINDOWS\system32\uxtheme.dll
就来到了MFC42.DLL这个模块的.text节了。好,我们按Ctrl+F,输入CALL [EBP+0X14],回车。搜索到的第一个结果就是:
73EFE935 FF55 14 CALL DWORD PTR SS:[EBP+14] ; 这句就是调用用户函数的CALL
现在明白本文题目的意思了吧。。。
下面来看看此法的应用。
随便找一个MFC42的CM,用OD载入,有壳,不用管,直接F9,然后ALT+E,双击MFC42.DLL,CTRL+F,输入CALL [EBP+14],在第一个找到的地址处F2下断点。
点CM的确定按钮,OD断下,F2删除断点,F7。
这里就是按钮的处理函数。可以分析了。
——————————————————————————–
【经验总结】
如果你看明白了我的过程,那么你也应该明白我的思路。
MFC42.DLL的特征码就是指令CALL [EBP+14]
顺便说一下,所有的按钮控件的处理函数OnXXXClick()都经过这里。并且,编辑框控件的OnChange()函数,以及其它很多控
件的消息,比如CheckBox的消息,甚至OnClose()也都经过这里。什么原因呢?因为MFC框架的消息分发过程,是按参数类型
模板分类的。如果不理解,就不用理解了,只要记住方法就行了。
另外,对所有的MFC程序,如MFC71D,MFC90U等,这个方法都可以用,并且静态连接的也可以,并且Delphi的程序也可以,只
要掌握了原理,方法大同小异。至于各自的“特征码”是什么,自己去找吧。
评论