首页
社区
课程
招聘
如何在IDA中找到MFC程序的消息处理函数
发表于: 2005-12-8 23:39 14549

如何在IDA中找到MFC程序的消息处理函数

bpx 活跃值
3
2005-12-8 23:39
14549

比起用Win32SDK写的程序,要分析MFC应用程序要麻烦不少。在前者,只要找到注册窗口类的地方就知道其WinProc的位置。那里是程序的控制中心,只要顺藤摸瓜就可以找到你感兴趣的地方。对于用MFC写的程序,这一切都变得复杂起来了。这时,所有的消息都是通过一套复杂的机制来完成分发的。他们是通过分发数据表来找到最终函数地址的. 详细请参阅MFC的源代码。

常见的消息分发数据是由以下的宏来生成的:
        ON_WM_SIZE()
        ON_NOTIFY(TCN_SELCHANGE, ID_TABBOARD, OnBoardSelchange)
        ON_WM_LBUTTONDBLCLK()
        ON_WM_LBUTTONDOWN()
        ON_WM_RBUTTONDOWN()
        ON_WM_TIMER()
        ON_COMMAND(ID_REDRAW_ALL, OnRedrawAll)

这里简单说一下如何找到二类消息的处理函数。一类是WM_XXX型消息,如WM_LBUTTONDOWN,另一类是WM_COMMAND型消息.

对于第一类,它的调用栈是:
CMyView::OnLButtonDown        <--最终目标
CWnd::OnWndMsg                <--找到这个函数就接近最终目标了
CWnd::WindowProc
AxfCallWndProc
AxfWndProc
AxfWndProcBase

以WM_LBUTTONDOWN为例

#define ON_WM_LBUTTONDOWN() \
        { WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp, \
                (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, CPoint))&OnLButtonDown },
AfxSig_vwp = 0x31

对于VC6.0 Release 版本,可搜索 C0 24 F0 83 C0 2F 48  83 F8 30 0F 87 C6 02 找到CWnd::OnWndMsg。
进入CWnd::OnWndMsg后,找到 case 0x30(IDA 中的case 0x30其实是 case 0x31)处的
call    ebx
将进入你真正感兴趣的地方!

这里必须用条件断点Dword(ESP+0x0c) == 0x201, (注WM_LBUTTONDOWN == 0x201) 否则这个断点总会遇到.

找WM_COMMAND消息处理的地方

对于第二类,它的调用栈是:
CMyDoc::OnCmdXXX        <--最终目标
_AxfDispatchCmdMsg        <--找到这个函数就接近最终目标了
CCmdTarget::OnCmdMsg
CDocument::OnCmdMsg
CView::OnCmdMsg
CFrameWnd::OnCmdMsg
CWnd::OnCommand
CFrameWnd::OnCommand
CWnd::OnWndMsg
CWnd::WindowProc
AxfCallWndProc
AxfWndProc
AxfWndProcBase

ON_COMMAND定义如下
#define ON_COMMAND(id, memberFxn) \
        { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSig_vv, (AFX_PMSG)&memberFxn },
其中的AfxSig_vv = 12

搜索 71 74 5C 48  48 74 53 83 E8 0A 74 46,将找到_AfxDispatchCmdMsg函数,在case 12 的地方设断点并运行,当程序需要处理OnCmdXXX的时候,控制就会跑到这里,单步进入就可以了。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 239
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好文章,果然是高人,支持!!!!!!!

建议版主加精华!!!!!!!!
2005-12-9 00:12
0
雪    币: 229
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
收下了。楼主不防写个小工具。
2005-12-9 00:22
0
雪    币: 208
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
顶啊
我以前也考虑过这个问题,但就是没有想到好的办法。
2005-12-11 13:13
0
雪    币: 207
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
学习。。。
2005-12-11 14:28
0
雪    币: 47147
活跃值: (20415)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
6
最初由 dssz 发布
好文章,果然是高人,支持!!!!!!!

建议版主加精华!!!!!!!!


才看到。;(
如果还有漏掉的好文章,还麻烦各位顶一下。
2005-12-11 20:22
0
雪    币: 136
活跃值: (429)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
7
不错,想当时也被困扰。。。
2005-12-11 21:04
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
楼主要是给合一个具体的例子来讲解就更好了
2005-12-11 21:57
0
雪    币: 298
活跃值: (445)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
9
好文章啊,第200个帖就留在这里啊.!!呵呵..
2005-12-11 23:01
0
雪    币: 254
活跃值: (126)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
最初由 kanxue 发布


才看到。;(
如果还有漏掉的好文章,还麻烦各位顶一下。


以后看到没加精的都去顶一下
2005-12-11 23:44
0
雪    币: 260
活跃值: (81)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
最初由 heXer 发布


以后看到没加精的都去顶一下

2005-12-12 01:40
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
12
确是好文章,差点漏掉~
2005-12-12 10:26
0
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
13
最初由 heXer 发布


以后看到没加精的都去顶一下

2005-12-12 16:23
0
雪    币: 440
活跃值: (717)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
14
正写出了我所需要的..

有没有更通用的办法?
找出delphi的,vb的,etc...
2005-12-12 16:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
非常好
2005-12-12 17:20
0
雪    币: 166
活跃值: (112)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
不必用ida,用ultraedit就行。方法如下
注意到mfc的消息列表有
  PAFX_MSGMAP_ENTRY = ^AFX_MSGMAP_ENTRY;
  AFX_MSGMAP_ENTRY = packed record
    nMessage: dword; // windows中消息代号,定义在WinUser.h中
    nCode: dword;    // 如果nMessage是0x0111(WM_Command),nCode代表扩展消息,例如WM_Exchange等.亦定义在WinUser.h中
    nID: dword;      // 控件ID, 与资源部分中控件的ID一致
    nLastID: dword;  //  = nID
    nSig: dword;     //  含义不清楚
    AFX_PMSG: dword; // 指向消息处理的具体代码的开始位置
  end;  

所以我们只要知道消息的类型,和发出消息的控件ID,就可以搜索找到这个数组,那么AFX_PMSG就是你需要下断的地址

基于类似的方法,vb,delphi都可以这样来找到事件的处理代码的起始位置。
我想,大部分现代编译器编译的程序也应该适用这种方法。

扩展开去,这种方法应该属于伟大的dead listing技术之一。如果有兴趣,我们能进一步解析mfc,delphi,vb等程序的结构,从而了解更多。《黑客反汇编揭密》那本书讲的基本就是dead listing技术(虽然有人认为那本书很不怎么的)。
2005-12-12 17:49
0
雪    币: 272
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
小楼GG在啊,顶一下!
2005-12-12 20:58
0
雪    币: 1866
活跃值: (95)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
好文章呀!支持!
2005-12-14 16:22
0
雪    币: 61
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
看过...就顶...............
2005-12-14 20:25
0
雪    币: 193
活跃值: (1384)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
20
谢谢小楼的方法,呵呵!
  比较好用!

  用bpx的方法,怎么用UE找不到
C0 24 F0 83 C0 2F 48  83 F8 30 0F 87 C6 02
  有人试验了吗?我用的是Release方式编译的啊!
2005-12-19 15:22
0
游客
登录 | 注册 方可回帖
返回
//