Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
C/C++本地代码调试
分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
goandgo
2015-04-19, 20:10 下午
探索窗体菜单点击后的执行流程。
断点下在WndProc处,命中后栈回溯如下:
ChildEBP RetAddr Args to Child
0030fb50 7680c4e7 001204b8 0000007f 00000002 ___________!WndProc (FPO: [Non-Fpo]) (CONV: stdcall) [f:\windbg\projects\go\消息处理过程拦截与调试\消息处理过程拦截与调试.cpp @ 127]
0030fb7c 7680c5e7 01321195 001204b8 0000007f USER32!InternalCallWinProc+0x23
0030fbf4 76804f0e 00000000 01321195 001204b8 USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])
0030fc50 76804f7d 007360e8 0000007f 00000002 USER32!DispatchClientMessage+0xda (FPO: [Non-Fpo])
0030fc78 76dd702e 0030fc90 00000018 0030fe30 USER32!__fnDWORD+0x24 (FPO: [Non-Fpo])
0030fca4 7680cde0 7680ce13 0030fdb8 00000000 ntdll!KiUserCallbackDispatcher+0x2e (FPO: [0,0,0])
0030fca8 7680ce13 0030fdb8 00000000 00000000 USER32!NtUserGetMessage+0xc (FPO: [4,0,0])
0030fcc4 01321a5e 0030fdb8 00000000 00000000 USER32!GetMessageW+0x33 (FPO: [Non-Fpo])
消息分发后的第一处是函数UserCallWinProcCheckWow,第二处是InternalCallWinProc。倒着进行分析两个函数,第一个函数是InternalCallWinProc。
断在WndProc窗口处理函数时,栈上结果如下:
0:000> dd esp
0030fb54 7680c4e7 001204b8 0000007f 00000002
0030fb64 00000000 0000007f dcbaabcd 00000000
解释如下:
7680c4e7:返回到InternalCallWinProc函数中的地址
001204b8:窗口句柄
0000007f:消息码
00000002:wParam参数
00000000:lParam参数
还原C代码如下是函数原型:
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
接下来,断点下在USER32!InternalCallWinProc函数处,看看栈中与断点下在WndProc中有什么差别。
bp USER32!InternalCallWinProc
断下后栈中情况如下:
0:000> dd esp
0030fb80 7680c5e7 01321195 001204b8 0000007f
0030fb90 00000000 00000000 ffb1c569 00000000
7680c5e7:这是返回到InternalCallWndProc的调用者的地址
01321195:这个是关键
001204b8:句柄
0000007f:消息
00000000:wParam
00000000:lParam
下面找一个这个地址01321195,从Disassembly窗口找一下,
_________________exe!ILT+400(?WndProcYGJPAUHWND__IIJZ):
01321195 e906060000 jmp _________________exe!WndProc (000617a0)
结果是WndProc的地址,现在这个关键是明确了。
总结:其实上面只是偶然,01321195 这个地址是偶然的,也有可能不是这个地址,当消息值是111(WM_COMMAND)时就会是这个地址,如果不是这个消息就有可能是其他的。毕竟其他消息也走这个路线,返回地址可能是其他函数,比如user32!ImeWndProc函数。
模拟一下USER32!InternalCallWinProc如下:
void USER32!InternalCallWinProc(LPVOID *lpWndProc,HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
USER32!UserCallWinProcCheckWow函数。首先说明一下栈回溯看到的一个现象--(FPO: [Non-Fpo]),后面的这些符号的意思是这个函数没有使用FPO优化,也可以这样说,ebp没有用到,或者说第一条指令不是push ebp的形式。
bp USER32!UserCallWinProcCheckWow下断点,并下断点bp WndProc,这样下两个断点是为了参照。
UserCallWinProcCheckWow断下时栈中内容:
001ef75c 76804f0e 00000000 01281195 001508bc
001ef76c 00000024 00000000 001ef800 005db54c
001ef77c 00000001 650f2517 001ef880 001efb58
InternalCallWinProc断下时栈的内容:
001ef6e4 7680c5e7 01281195 001508bc 00000024
001ef6f4 00000000 001ef800 650f25fb 00000000
001ef704 001508bc 00000000 00000024 00000001
WndProc断下时栈的内容:
001ef6b8 7680c4e7 001508bc 00000024 00000000
001ef6c8 001ef800 00000024 dcbaabcd 00000000
001ef6d8 001ef730 00000024 001ef758 7680c5e7
三个对比一下,
76804f0e:反回UserCallWinProcCheckWow的调用者中的地址
00000000:这个是关键,是第一个参数
01281195:WndProc地址(是间接地址,是jmp Wndproc指令的地址)
001508bc:句柄
00000024:消息
00000000:wParam
001ef800:lParam
Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
兴兴
2015-05-01, 22:35 下午
看了下你的分享,我也经常会想跟踪消息处理,可能是我比较菜,感觉这个挺难的,想和你多交流
Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
格蠹老雷
2015-05-08, 21:50 下午
写的挺好的,谢谢分享
Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
兴兴
2015-05-08, 23:09 下午
嘿嘿,没想到可以看到雷老师。雷老师,我有一些疑惑,不知道您有没有时间解答。窗口过程也就是消息处理过程,可以用setWindowlong设置子过程外,还有没有其他方式可以改变或增加处理过程。
Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
goandgo
2015-05-10, 16:46 下午
谢谢雷老师的支持。
终于又可以回帖子了,前几天不能回帖子也不能发表,联系咱们的管理人员也没有联系上。
雷老师的书写的确实不错,但是限于我能力有限,有些地方不是特别明白,平实学习也就是操作一下,乱写的。
Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
goandgo
2015-05-10, 16:47 下午
其实我也是才开始学没多长时间,有些都是凭自己的感觉写的,我在看雷老师的书,以后多交流!
Re: 分享一次未成功的跟踪菜单点击处理流程的经历(如果有同样经历的可分享一下经历)
格蠹老雷
2015-05-10, 21:15 下午
都是同行,别客气,多交流