如何在IDA中找到MFC程序的消息處理函數

比起用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的時候,控制就會跑到這裏,單步進入就可以了。

 

 

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章