整理OD学习之深入理解消息循环

原文转自:逆向工程-------OD学习之深入理解消息循环  本文略加整理。以下是原文部分:"

今天我们一起深入探讨下带有对话框的消息循环。先看下图:今天我们就来研究这个图!!

整理OD学习之深入理解消息循环_第1张图片
为了方便研究,我就选用看雪实例里的一个程序。从图上你可以看出一个主窗口,还有一个消息框。为了程序界面的简单,还请暂时把你看到的这个消息框当成对话框。这样一来你所看到的2个元素分别就是:主窗口和一个对话框。
现在我们就来模拟下你按下“OK”按钮后,系统到底做了些什么操作。
当你按下此按钮,系统就是构建一个消息结构
MSG {“按钮句柄”,“WM_LBUTTONDBLCLK”,参数1,参数2,“此时鼠标在屏幕中的坐标”}
之后把这个消息结构放到系统消息列队。之后系统会看情况把这个消息放入主窗口的线程消息队列中。
这个时候我们的主窗口消息循环中的GetMessage函数就会去自己的线程消息队列里取消息,如果没有取到,那么这个函数是不会返回的,原线程挂起同时发起线程的切换。(在此感谢刘飞同学的补充理解),如果取得消息的话,那么DispatchMessage函数就会分析这个MSG结构从而获得这个“按钮的句柄”,那么DispatchMessage就会调用这个按钮的回调函数(按钮回调函数包含在USER32.dll中)。按钮的回调函数会重新构建这个MSG,使其变成:
 MSG{“按钮父亲窗口的句柄(TrackMe对话框的句柄)”,WM_COMMAND,“OK按钮的资源号”,0}
并且把重新构建好的MSG结构再次放入主窗口消息队列中。这个时候GetMessage函数继续取消息,而这个时候的消息里的内容已经有所变化,DispatchMessage函数分析新来的MSG结构获得的句柄已经是对话框窗口的句柄,这个时候DispatchMessage函数就会去调用对话框的消息回调函数,令人兴奋的是,对话框的消息回调函数是程序员自定义的。这样一来,按钮的点击就和过程函数扯上了关系。
当然啦,上面说的还是比较的肤浅,其实里面还涉及到更多的消息的转换,我就不介绍了,有兴趣的读者用OD跟下就会发现其细节。

"

    上面的转载中,我标红了两处比较重要的信息:控件的消息,和转发到父窗口的WM_COMMAND消息。下面,我以windbg调试calc.exe为例,演示作者的意图。

    以Button 0为例,它的句柄值为0206006

整理OD学习之深入理解消息循环_第2张图片

Button 0的控件ID:0x0082

整理OD学习之深入理解消息循环_第3张图片

Button 0的父窗口信息:

整理OD学习之深入理解消息循环_第4张图片

    它的父窗口看着像是一个组合框,它的句柄值为06057E,和SPY++获得的结果一致。

整理OD学习之深入理解消息循环_第5张图片

    要验证原作者的结论是否正确,只需下在user32!InternalCallWindProc函数(前面的文章说过这是个万能消息断点)处对WM_LBUTTON和WM_COMMAND消息下条件断点:

0:004> bp USER32!InternalCallWinProc ".if((dwo(esp+8)==00020606&dwo(esp+c)==201)|(dwo(esp+8)==0006057E&dwo(esp+c)==111)){.echo LB;}.else{gc;}"
运行windbg并在Button 0上按键,windbg马上会中断在Button 0的user32!InternalCallWindProc函数处,此时打印调用堆栈:

0:004> g
LB
esp=0016ee14
USER32!InternalCallWinProc:
7596c494 55              push    ebp
0:000> kb
ChildEBP RetAddr  Args to Child              
0016ee10 7596c5b7 7455b4a9 00020606 00000201 USER32!InternalCallWinProc @注释 参数2:00020606是spy++给出的Button 0的句柄值,参数3:0x201是鼠标左键按下的消息
0016ee88 7596cbe9 00000000 7455b4a9 00020606 USER32!UserCallWinProcCheckWow+0x14b
0016eee8 7596cc40 7455b4a9 00000000 0016fc68 USER32!DispatchMessageWorker+0x357
再次运行windbg,它会再次中断在组合框的user32!InternalCallWindProc函数处,此时打印调用堆栈:

0:000> g
LB
esp=0016ebc4 
USER32!InternalCallWinProc:
7596c494 55              push    ebp
0:000> kb
ChildEBP RetAddr  Args to Child              
0016ebc0 7596c5b7 75985b91 0006057e 00000111 USER32!InternalCallWinProc @注释 参数2:0006057e是spy++给出Button 0的父窗口的句柄,参数3:111是WM_COMMAND消息
0016ec38 75964ede 00000000 75985b91 0006057e USER32!UserCallWinProcCheckWow+0x14b
0016ec94 75964f4d 00787e10 00000111 00000082 USER32!DispatchClientMessage+0xcf
...
综上所述,恰如原作者所述:控件上的消息会被转换成父窗口的WM_COMMAND消息。




你可能感兴趣的:(调试,win,器之卷)