文章目录
  1. 1. 原始程序
  2. 2. OD中截获WM_COMMAND消息
  3. 3. 内存断点法
  4. 4. 函数断点法
给大家介绍下OD中怎么设置消息断点吧,本文只针对C/C++程序,别的语言写的程序有更好的办法.

原始程序

随便写一个对话框程序给大家演示一下吧.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <Windows.h>
#include "resource.h"

BOOL CALLBACK DialogProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{

switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
MessageBox(0,"OK","OK",0);
return 0;
}
case WM_SYSCOMMAND:
if(LOWORD(wParam)==SC_CLOSE)
{
MessageBox(0,"Exit","OK",0);
EndDialog(hWnd,0);
}
}
return 0;
}

void main()
{

DialogBox(0,MAKEINTRESOURCE(IDD_DIALOG1),0,DialogProc);
}

程序很简单,点击OK按钮出来一个提示框

OD中截获WM_COMMAND消息

开始想着是OD中选择查看->窗口,会显示当前应用程序的各个窗口,那直接找窗口处理函数,直接设断不就行了吗?很不幸,这样不行,看看下图



确实有确定,取消这几个按钮,而且也有我们的Dialog对话框,但是貌似处理函数跑飞了,我们自己写的处理函数怎么会位于USER32.DLL的加载空间呢?不用问,不是这个,仔细看下,上面写的是ClsProc,而且左边还有个WinProc,我的理解是WinProc才是你自己写的函数,但是这里OD没检测出来,那么ClsProc是什么呢?我的理解是,在RegisterClassEx中使用的WNDCLASSEX结构体中的窗口处理函数,那么,调用顺序是怎样的呢?Windows会首先调用ClsProc中的处理函数,再由这个函数将消息转发给咱们自己定义的函数.

  • 说了这么多,其实总结下来就一句话:这个ClsProc不一定靠谱,当然,一些情况下还是可以用他的,如果他可以用的话,就可以直接使用OD提供的设置消息断点的方式

那么,怎么办呢?这里给大家介绍两种方法.

内存断点法

  • 上面讲过,系统会先调用这个ClsProc,然后再调用我们自己提供的函数.看看地址空间,ClsProc显而易见是在USER32.DLL的空间(之前听有些说法是把它叫做系统空间,其实个人感觉这个不能叫系统空间,系统空间是指你运行了特权指令,int 0x2e,sysenter以后CPU进入0环以后的空间),而我们自己提供的函数肯定是位于当前应用程序的空间了,我们的目的就是找到他!

  • 首先,在ClsProc的位置下条件断点.





这里注意两点,第一个是地址77D3E577,由于动态链接库每次加载的位置都不一样,所以这个值可能是会变的;第二个是[esp+4]的值,也就是句柄值,这里也是不确定的,我是怎么得到这个值的呢?注意看堆栈,不多解释.

  • 点击确定后,程序断在这里,然后ALT+M打开内存,在代码区设断




  • 点击运行:




OK

函数断点法

首先问一个问题:Windows系统在显示对话框时会调用什么函数?你可能想说DialogBoxA,DialogBoxW,对不起,不是这两个,这两个其实不叫函数,他们只是宏定义,系统会调用DialogBoxParamA,或者DialogBoxParamW.看先调用接口:

1
2
3
4
5
6
int DialogBoxParam(
HINSTANCE hInstance,
LPCTSTR lpTemplateName,
HWND hWndParent,
DLGPROC lpDialogFunc,
PARAM dwInitParam)
;

思路有了吧,直接在这个函数上设断,[ESP+0x10]的值就是我们要找的了.

That’s all
文章目录
  1. 1. 原始程序
  2. 2. OD中截获WM_COMMAND消息
  3. 3. 内存断点法
  4. 4. 函数断点法