首页
社区
课程
招聘
[原创] 精准型消息断点
发表于: 2023-5-28 00:56 17025

[原创] 精准型消息断点

2023-5-28 00:56
17025


前文作为系列的开篇,我们站在Notepad.exe的视角,看它接过系统传来的消息,交由Notepad的窗口处理函数(WndProc)进行处理的过程。User32.dll!DispatchMessage API是前面"系统传来"中的一环,也是最靠近应用层的一环,将窗口消息传递给应用。本文从该API切入,逐渐远离熟悉的应用层。


[原本本文我想结合Ollydbg的消息断点演示,奈何消息断点存在各种限制,因此我在DispatchMessage上下条件断点,更精准的达到相同目的]

用过Ollydbg的读者一定对Ollydbg中的条件断点并不陌生,我先演示使用条件断点的标准流程。


上图Ollydbg的堆栈区窗口中:

a.ESP指向调用USER32.RegisterClassExW API的指令的返回地址 ;

b.ESP+4存放RegisterClassExW的参数WNDCLASSEX结构的地址,其结构定义如下,其中域变量lpfnWndProc位于结构体中的Offset 8 Byte处:

PS:虽然lpfnWndProc标注为窗口过程地址,但是只有少数CrackMe在lpfnWndProc指向的函数中进行消息处理。因此,只在此处未必是解决CrackMe的银弹。这才引出使用DispatchMessage追踪窗口函数的必要性。


Ollydbg的堆栈区窗口中"ESP+4"处右键"Follow in dump",即可在数据区查看WNDCLASSEX各个域变量的值。图中0x19FB64(WNDCLASSEX + 0x08)处存放Notepad窗口过程(WndProc)地址(0x401B90):

在Ollydbg数据区0x19FB64处右键"Follow DWORD in Disassembler",即可在指令窗口显示Notepad窗口过程的反汇编。(我用LoadMapEx加载了Notepad的map文件,因此Comment区域会显示窗口过程的符号名_NpWndProc)Notepad的窗口过程位于0x0401B90(很明显该过程位于Notepad.exe 代码段内),先记录这个地址并在下断点

通过分析RegisterClassEx的参数,我们认为Notepad的窗口过程位于0x0401B90,然而,Ollydbg工具栏中"W"给出的窗口过程/ClsProc都没给出这个地址

对于CrackMe练习,一般下一步是在Edit窗口ClsProc上下消息断点,奈何消息断点在单文档窗口程序上似乎失效了(百度搜索"消息断点失效",提问者不少解答者寥寥),于是变通为给DispatchMessageA/W下条件断点。DispatchMessage的唯一参数为MSG,结构如下:


DispatchMessageA/W下条件断点的步骤如下:

a. 先给DispatchMessage下个普通断点(bp DisaptchMessageA/W),断下后结合堆栈来拼凑成条件断点;

据此,得到DispatchMessageW条件断点的表达式: 

当Notepad收到按键抬起消息时,ollydbg会中断在条件断点处。一般为了追踪处理消息的窗口过程中,Cracker此时会在Ollydbg中对代码段下内存访问断点。对于本文就是对Notepad的代码段下内存访问断点。

点击Ollydbg工具栏的"M",显示模块窗口:

再次运行ollydbg,程序马上会暂定在Notepad的代码段中,暂定处大概率是窗口过程。对于CrackMe,剩下的是分析注册码算法了,但是此处,我提出2个调试过程中遇到的值得深思的问题:

a.如果Notepad.exe的代码量极大,窗口过程恰好位于其他dll中,那么通过下内存访问断点来定位窗口过程的方式是不是失效了?

b.有别于练手的CrackMe程序,对于多线程程序,就如Notepad.exe,设置内存访问断点后,其他线程也会访问代码段(如访问网络读取数据),如何从中挑选出窗口过程?这无异于引入了大量的噪声,增加的分析的难度。(简单如Notepad.exe也有15个线程)

如何解决上述2个问题?让我们深入DispatchMessage函数。



[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 14517
活跃值: (17538)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-5-30 09:34
0
雪    币: 1309
活跃值: (5159)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
谢谢,学习了。
2023-5-30 09:37
0
雪    币: 871
活跃值: (9841)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
4

学到了. InternalCallWinProc 可以定位精确消息断点. 解决调试根本. 上边的内存下断都是调试技巧. 收藏. 谢谢分享.


做个备份.以后看.


总结:

DispatchMessageW最终会调用到 InternalCallWinProc 

下面是他原型.

#define InternalCallWinProc(winproc, hwnd, message, wParam, lParam)    \
    (winproc)(hwnd, message, wParam, lParam)

那么可以对 InternalCallWinProc 下断. 参数一则是 Winproc. 可以过滤此值当命中在自己的模块空间中就断下.

那么大概率就是 处理此消息的窗口过程回调.

最后于 2023-5-30 10:22 被TkBinary编辑 ,原因:
2023-5-30 09:57
3
雪    币: 802
活跃值: (4433)
能力值: ( LV12,RANK:260 )
在线值:
发帖
回帖
粉丝
5
TkBinary 学到了. InternalCallWinProc 可以定位精确消息断点. 解决调试根本. 上边的内存下断都是调试技巧.& ...
哥,你的评论都要写的比我这篇文章认真了
2023-5-30 13:07
0
雪    币: 802
活跃值: (4433)
能力值: ( LV12,RANK:260 )
在线值:
发帖
回帖
粉丝
6
TkBinary 学到了. InternalCallWinProc 可以定位精确消息断点. 解决调试根本. 上边的内存下断都是调试技巧.& ...
internalcallwinproc其实要借助调试符号才能定位
2023-5-30 13:11
0
雪    币: 871
活跃值: (9841)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
7
hyjxiaobia 哥,你的评论都要写的比我这篇文章认真了
没有没有,是你写的好. 哈哈. 
没有调试符号不好找. 不过 知道总比不知道强.
2023-5-30 13:41
0
雪    币: 1810
活跃值: (4020)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8

感谢分享

最后于 2023-5-30 14:52 被小希希编辑 ,原因:
2023-5-30 14:04
0
雪    币: 364
活跃值: (1726)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
谢谢,学习了
2023-9-19 14:43
0
雪    币: 3059
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享
2023-11-8 09:29
1
游客
登录 | 注册 方可回帖
返回
//