欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]修正OD1.1中消息断点的Bug

[原创]修正OD1.1中消息断点的Bug


    1.OllyDbg1.10在调试unicode窗口类型程序(记事本程序为例)的时候无法下消息断点,每次下消息断点的时候,OllyDbg1.10会弹出窗口。
        
    OllyDbg1.10设置消息断点的方法为:


    1.选择查看菜单下的窗口按钮或者直接点击工具栏中的W图标,即可获得窗口列表。
        
    2.然后在窗口列表中鼠标左键点击选中要设置消息断点的窗口,被选中窗口会被灰化表明被选中。
        
    3.右键单击在弹出菜单中选择设置消息断点。
        
    4.在弹出的窗口的消息列表中根据自身的需要设置各种消息断点。
        

    2.FFFF026A位于进程中的高2G地址,这个地址存在问题。为了确定该问题的产生原因,使用OllyDbg1.10(调试程序)调试OllyDbg1.10(被调试程序)。然后让OllyDbg1.10(被调试程序)正常运行并调试记事本程序,重现该问题。
    3.对于弹出的窗口,根据该窗口的样式,非常怀疑是调用MessageBox函数弹出的对话框。为了验证这一猜测,在OllyDbg1.10(调试程序)中对OllyDbg1.10(被调试程序)的user32.dll中的4个MessageBox函数中的返回处下断点。
        
    4.点击窗口的确定按钮,发现OllyDbg1.10(被调试程序)中断在函数MessageBoxExA的返回处。
        
    5.查看栈回溯窗口,可以确定调用该函数的用户代码位于00454059的上一行代码。
        
        
    进入用户代码进行观看可以发现,该块函数代码含有参数:EBP+8和EBP+C,但是函数在返回的时候直接使用retn,并没有平衡栈,因此该函数属于C调用约定。
        
    6.通过栈观察传递给该函数的两个参数的数值分别为:004B285F和FFFF026A。对于FFFF026A,一开始的对话框的信息中便包含该数值。而对于004B285F十分像是一个指针,前往内存区域观看该数据,可以发现该处内存区域的数据正是对话框的文本信息。因此,没有必要观看该块函数的处理流程,继续往上回溯。
        
    7.重复以上流程最终可以确定数值FFFF026A来源于00498D33处的代码操作。也可以直接通过观察栈回溯窗口,即可进行确定。数据位于EBX+24h处,即02300024。
        
    现在做两个测试进行验证:
    1.修改00498D33处的代码操作传递的数值为FFFF026B,观察弹出的对话框的信息是否会进行相应的改变。
        
        
        根据对话框的弹出信息可以确定该信息并没有被更改过。
    
    2.修改02300024处的数值为6B,查看OllyDbg1.10(被调试程序)的ClsProc是否会发生改变。通过对以下两幅图的对比,可以发现随着数值的变更,对应的ClsProc数值也会发生改变。
        
        
    8.对02300024处的数值下硬件写入断点,然后在OllyDbg1.10(被调试程序)中刷新窗口。代码停在004A3547处,观察此处代码可以确定为memcpy(dst, src, len)。其中目标地址为0230000,源地址为0012EBD0。
        
    9.直接观察栈回溯窗口,直接根据函数参数可以确定0012EBD0的地址的确定位于函数00497A64中。
        
    10.进入函数观察发现以下一系列ASCII类函数,然而我们的窗口对象是UNICODE类型对象,此时怀疑该问题产生的原因为函数掉用错误。
        
    为了验证我们的猜想,在GetWindowLongA处下断点,并再次刷新OllyDbg1.10(被调试程序)的窗口。最终,在GetClassLongA处发现返回数值FFFF026A。到此为止,可以确定问题出现在GetClassLongA处。
    对于有过windows开发经验的人员而言,在看到ClsProc的数值为FFFF026A的时候,基本上就可以直接怀疑是GetWindowLong,GetClassLong等的函数的返回数值存在问题。因此,我们可以直接在这4个函数的返回处下条件断点,当返回值为FFFF026A的时候,中断被调试程序。
        
    11.确定了原因之后,我们需要想办法解决掉这个问题,有以下几种方案:
        1.直接对程序打补丁。
            优点:方便,快捷。
            缺点:不够兼容和不易维护。
        2.OllyDbg1.10提供了插件功能,可以利用插件的方法对OllyDbg进行修改。
            优点:兼容可维护,易于扩展。
            缺点:不够快捷,方便。
    12.如果直接对程序打补丁,通过观察可以发现OllyDbg1.10的代码空间并没有足够的空闲空间,如果想要增加代码的话,不得不修改OllyDbg1.10的文件结构。这样做起来很麻烦。因此最好还是利用OllyDbg1.10的插件功能进行修改。
    OllyDbg1.10的插件必须是 DLL 格式的,因此必须要把你所用到的回调函数输出。另外,在编程中应该将char默认设置为unsigned,在VC编译器中也就是加一个“/J”的编译参数。
    编写OllyDbg1.10插件必需要有以下两个导出函数:
    extc int  _export cdecl ODBG_Plugindata(char shortname[32]):必须填充插件名和返回插件所适合的 OllyDbg 版本号(常量是 PLUGIN_VERSION),如果函数不正确,或者版本不兼容,插件就不会安装。该短标识名用于标识插件,其最长 31个 字符(或包含空格),其最后是结尾的NULL。
    extc int  _export cdecl ODBG_Plugininit(int ollydbgversion, HWND hw, ulong *features):可以将所有需要初始化和分配的资源放在这个函数里。如果启动成功,函数必须返回 0,发生错误返回 -1,那样插件就会卸载,参数 ollydbgversion 是插件可以兼容的OllyDbg的版本号。
    13.要对OllyDbg1.10调用GetClassLongA这一过程进行修复。在这里,我们首先要确定一下修复的地点应该放在哪里:

        1.通过查找参考可以发现OllyDbg1.10不止在一处调用了GetClassLongA。这种情况下,就不适合在流程的上游进行修改,应该在流程的下游某处来进行修改。
        2.又由于OllyDbg1.10调用 GetClassLongA流程的都是将通过一个跳转,间接获取输入表项的数值进行调用。因此可以通过修改这两个地方的任意一处即可。
        3.在这里我就直接选择导入表中的数值进行修改。

    14.确定了替换的位置以后,我们要回忆一下替换程序流程的思路:
        1.保存要修改的代码:GetClassLongA的地址。
        2.将代码的执行流程修改到我们自己写的函数中。此处需注意,因为我们需要在Fun中执行自身的代码,OllyDbg1.10在调用call GetClassLongA以后,他的函数参数在栈中的布局已经确定,如果我们声明一个和原先函数的调用约定与传参一样的函数,就可以直接使用,因此我在这里直接声明新的函数为:DWORD __stdcall GetClassLong_Procedure_New(HWND hWnd, int nIndex)。
        3.在函数中添加要执行的代码:判断句柄是否为Anscii版本,如果是,则调用GetClassLongA。此处需要注意,即使判定了为Anscii版本,GetClassLongA对于Windows一些控件的获取仍旧存在问题,返回值是一个大于0x80000000的地址,此时仍需调用GetClassLongW。
        4.因为函数调用约定与传参一样,函数的返回数值即为求取的数值。

    15.确定了替换程序流程思路以后,我们要再回忆一下修改代码的思路:
    在DLL装载的时候:
        1.因为OllyDbg1.10有重定位表,因此先获取模组的首地址。
        2.计算偏移地址量到输入表项。
        3.拷贝原来的代码并修改相关全局变量。
        4.修改原来的代码。
    在dll卸载的时候:
        检查是否对OllyDbg1.10进行了修改。如果存在修改,恢复原来的代码。确保OllyDbg1.10的正常执行。

    16.作为科锐的一员,祝愿科锐(http://www.51asm.com)越办越好。在科锐已经有大半年了,学习C语言的时候,我真正的掌握到了面向过程和分工的概念。学完C++、CAD和MFC以后,我才彻底明白面向对象的精髓。等到学完数据结构和关系以后,我在对软件的认知上更是有了本质的突破。突然回想了一下这段时间的学习经历,真的是受益终身。最后,也祝大家在软件逆向和调试这条道路上一路高歌。
代码请参考附件。

上传的附件 无标题.png
无标题1.png
无标题2.png
无标题3.png
无标题4.png
无标题5.png
无标题6.png
无标题7.png
无标题8.png
无标题9.png
无标题10.png
无标题11.png
无标题12.png
无标题13.png
无标题14.png
cr20.zip
1.0.png
1.1.png
1.2.png
1.3.png

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功