MFC消息分析
记得前一段时间,我刚接触软件破解和逆向这一行时,对于一些软件不知从何处跟踪按钮消息,试了好多方法,就是断不下来,在系统模块中经常转得晕头转向,而一无所获。
MFC程序是一种常见类型的程序,我静下心来,潜心研究了一下MFC消息流程。弄清原委之后,一切豁然开朗,发现跟踪MFC程序和消息处理原来是如此。。。,跟踪按钮事件处理也由此变得特别简单。
于是,我将这些研究整理成文,以备后忘。并希望对和我一样的菜鸟有所帮助,有误之处,请高手指正。
本文目的就是以一个MFC的标准对话框程序为例,同时从源码和反汇编代码两方面来研究MFC消息的流程走向,弄清MFC消息路径的所有站点,这样就可以任 意定位MFC的所有消息事件,可以从任一站点切入,进行跟踪分析MFC的处理过程。甚至可以从PumpMessage大本营出发,一直全程跟踪,做到心中 有数,不慌不乱。
关于对话框的启动过程,其过程很简单,程序进入WinMain函数之后,会调用对话框的DoModal函数,然后就进入RunModalLoop函数,消 息循环在这里就开始了,限于篇幅,本文不作多说,有兴趣者可看看MFC源码。本篇重点在于分析MFC的消息分发处理的过程。
先看一下RunModalLoop函数部分源码:
int CWnd::RunModalLoop(DWORD dwFlags)
{ …
for (;;)
{ …
do
{ if (!AfxGetThread()->PumpMessage()) // pump message, but quit on WM_QUIT
{
AfxPostQuitMessage(0);
return -1;
}
…
} while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
}
…
}
这里,AfxGetThread()->PumpMessage()是MFC消息处理的大本营,MFC程序的所有消息就是从这里开始,经过重重路径 转换,翻山越岭,中途直达Windows系统内核,再返回到MFC地界,又途经不少周折,才找到最终目的地 – 消息函数地址。可谓是山重水复疑无路,柳 暗花明又一村。
一个按钮点击事件的过程如下:
CWinThread::PumpMessage -> CWnd::PretranslateMessage -> CWnd::WWalkPreTranslateMessate -> CD1Dlg::PreTranslateMessage -> CDialog::PreTranslateMessage -> CWnd::PreTranslateInput -> CWnd::IsDialogMessageA -> USER32 内 核 -> AfxWndProcBase -> AfxWndProc -> AfxCallWndProc -> CWnd::WindowProc -> CWnd::OnWndMsg -> CWnd::OnCommand -> CDialog::OnCmdMsg -> CCmdTarget::OnCmdMsg -> _AfxDispatchCmdMsg -> CD1Dlg::OnButton1()
VC下,可以随手写一个标准的对话框程序,上面放一个按钮,点击按钮后,弹出一个消息框。我们现在就从PumpMessage()开始,来分析这中间的消息流程:
1. CWinThread::PumpMessage函数 (消息泵)
BOOL CWinThread::PumpMessage()
{ //GetMessage 当消息为WM_QUIT时,返回0,其它消息时,返回TRUE,有错误时,返回-1
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)) return FALSE;
if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);
::DispatchMessage(&m_msgCur);
}
return TRUE;
}
PumpMessage只有在接收到WM_QUIT消息时,才返回FALSE,其它情况,返回TRUE。由于CWinThread::PumpMessage()函数负责从消息队列中获取消息、翻译消息以及分发消息等,因此习惯将此函数称之为“消息泵”。
在PumpMessage函数中,PreTranslateMessage函数至关重要,正是有了这个PreTranslateMessage(),才使 得MFC能够灵活的控制消息的分发模式,可以说,PreTranslateMessage()就是MFC的实现消息分发模式的工具。
MFC-Msg.rar (202.8 KiB, 615 hits)