滴水逆向---资源文件_消息断点_ReverseTraining_3.exe

文章详细介绍了如何使用x32dbg进行Windows程序调试,包括MAKEINTRESOURCE宏的作用,WinMain函数的参数解析,以及通过设置消息断点来追踪处理函数,特别是利用_IAT表找到函数地址,识别_stdcall调用约定,并在遇到复杂的程序时如何定位消息处理代码。此外,文章还讨论了如何通过条件断点捕获特定类型的消息,如WM_COMMAND,以及如何在系统DLL中找到程序的消息处理逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、资源文件

MAKEINTRESOURCE:这个宏用于将数字转换为char*类型

返回值

1.窗口程序:

已处理的消息返回0

未处理的消息用DesWindowProc()函数返回,交给操作系统处理

2.资源文件:

已处理的消息返回TRUE

未处理的消息返回FALSE

二、消息断点

1.方法一

将程序拖进x32dbg里面
在这里插入图片描述

往下走,找入口函数WinMain

WinMain函数有四个参数,其中第一个参数hInstance就是模块的句柄,在这里就是PE结构里面的Windows输出进程基址ImageBase

往下走到这儿,我们看到这个函数叫GetModuleHandleA,我们往Microsoft里面一查,发现这是一个用来获取模块句柄的函数

另外,我们发现这不是平时我们见到的E8 CALL,而是一个FF间接CALL,所以立马就想到了PE结构
在这里插入图片描述
输入dd命令查看00405010处的内存,发现里面刚好存储的就是这个函数的名称
在这里插入图片描述
由此我们可以想到这里就是一个IAT表,用IAT表将函数的名称读出来,就是我们反汇编窗口右边能看到的红色字符串了

往上验证一下,我们看到了WinMain另外的三个参数
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
回到GetModuleHandleA那行,我们看到它的下一行是一个push eax。一般情况下我们的返回值就是存在eax里面的

另外,_stdcall和_fastcall是内平栈,而cdecl用的是外平栈。显然,这里是个内平栈.我们跟进下面这个call 4010D0,发现它并没有用到寄存器传参,而且它的ret返回值刚好为0x10,也就是十进制的16,代表传了4个参数进去。也就是说,这个函数是_stdcall调用约定,而WinMain入口函数也恰好是_stdcall。所以我们可以初步判断这个函数是入口函数WinMain了
在这里插入图片描述
举一个例子:当A调用B时,假设有四个参数,就会push进去四个值,然后调用B。但是在执行call之前还会将执行调用语句时的下一行地址也压进栈里面

因此,上面这个DialogBoxParmA函数调用前会先执行五个push,最后一个push是调用DialogBoxParmA函数时的下一行地址,前面四个参数就是WinMain入口函数的四个参数

而WinMain函数用的是_stdcall调用约定,它执行参数压栈操作时是从右往左进行,而回调函数的地址存储在从左往右第三个参数,命令行参数里面,反过来一数就是下面这个DlgProc存储的401000
在这里插入图片描述
然后我们ctrl+g跳转到401000,F2下断。切记不能直接运行,因为消息事件是一直都在发生的,如果现在下一个断点直接运行,程序一检测到消息就下断,导致在这里不停下断,无法继续调试
在这里插入图片描述
所以我们需要下一个消息断点。我们将断点重新编辑,给它添加一个条件
在这里插入图片描述
由于消息处理函数存在下面这样一个机制:按钮产生的消息,最后都会传到父窗口的消息处理函数中,而消息的类型最后都会转换为WM_COMMAND类型
在这里插入图片描述
再加上MSG消息队列里面的第二个成员才是消息的标识符,这里的[esp+0]存储的是MSG结构体的this指针,也就是说,[esp+8]才是第二个成员
在这里插入图片描述
在这里插入图片描述
所以写入的条件就是当[esp+8]里面存储的消息类型为WM_COMMAND的时候,程序下断
在这里插入图片描述
现在就成功下断,并且不会连续下断了
在这里插入图片描述
并且程序的运行界面也弹出来了
在这里插入图片描述

2.方法二(当程序很复杂的时候)

把程序拽进去后直接运行,然后点进上面的Windows窗口(红色下划线处),右键刷新
在这里插入图片描述
我们可以看到有一项叫ClsProc,很明显这些地址都是7开头的。学过PE我们知道,7开头的地址已经到了系统DLL的领空。也就是说这个是系统DLL给我们指定的消息处理函数,并不是我们这个程序自己写的消息处理函数

我们尝试点击窗口上的按钮,发现它仍然能弹出程序自己写的消息处理函数的处理结果,也就是说,这些系统DLL指定的消息处理函数最终都会调用程序自己写的消息处理函数

我们可以右键右键Follow ClsProc,跟到几个按钮的地址处下消息断点
在这里插入图片描述
或者直接右键Message breakpoint on access,让OD直接帮我们下一个消息断点

而经过我们测试,发现鼠标左键按下没反应,释放鼠标左键时消息弹出,因此判断这个断点类型为202 WM_LBUTTONUP,这个是鼠标释放的消息
在这里插入图片描述
成功下断!
在这里插入图片描述
我们转到断点,重新编辑该断点,发现和我们之前手动写的条件断点如出一辙。所以消息断点其实就是条件断点
在这里插入图片描述
单击按钮让事件发生,我们发现这个下断的地址下在了系统的DLL领空,但是不知道真正的处理函数在哪里
在这里插入图片描述
于是,我们点击上面这个大写的M,来到Memory map
在这里插入图片描述
学过PE之后一眼就能看出来节表的位置
在这里插入图片描述
我们在.text段下一个Set memory breakpoint access访问断点,程序执行系统DLL指定的消息处理函数,最终都会调用程序自己写的消息处理函数,一调用就会立马下断

F9运行,我们发现程序已经断下来了
在这里插入图片描述

但是存在一个问题,就是消息事件是不断发生的,可能下断的时候传的消息并不是我们想要找的鼠标释放事件。如果我们一直单步往下走,可能直接就不知道跟到哪里去了

学过消息回调函数后,我们知道,回调函数堆栈里面,最上面是调用地址,第二个是句柄,然后是Message消息类型

我们看到右下角堆栈窗口,发现第三个并不是我们想要的111 WM_COMMAND消息
在这里插入图片描述
于是我们单步往下走,执行完retn 0x10后又跳回到了另一个DLL领空
在这里插入图片描述

我们再次F9运行,跑到下一个断点停下。一直循环这几个步骤,直到堆栈窗口的消息类型变成111为止
在这里插入图片描述
一直往下单步,最后就找到了我们下断时点击的Button 1的MessageBoxA了
在这里插入图片描述

本文为滴水三期的学习笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值