问题
使用“无银第八哥”给注册表 API 下断点,结果调用极其频繁,如果一个个人工去看,容易逐渐失去耐心。毕竟,挨踢太卷了!
解决
您只需要“条件断点”!但是怎么写“条件”成为拦路虎。
好在,“无银第八哥”自带了一份很简要的学习材料,您可以在帮助菜单打开,或按 F1,或在命令窗口输入 .hh
打开,然后输入“conditional breakpoints”,将进入一篇名为《Conditional breakpoints in WinDbg and other Windows debuggers》的帮助文档。
“条件断点”建议的使用方式是,把条件写到文件里,方便复用。指定一个断点的条件为某个文件内容的语法是:
1 | bp function "$$<C:\\commands.txt" |
当然,文件的内容才是重点,将在后面的实践例子里讲解。
实践
需求
winver
显示的 Windows 的 Relase 版本信息,比如“22H2”,是从注册表里读的,想断下这个读取。
实现
以下在 Windows 11 x64 下进行。
- 下断点前,需要先知道这个 Release 信息保存的注册表位置:
- 主键:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
- 值:DisplayVersion
- 数据:即是需要获取的 Release 信息
-
但是
winver.exe
的导入表里并没有任何 Reg API,反而这个程序的核心就是调用 SHELL32!ShellAboutW 而已。 -
查看
SHELL32.dll
的导入表,发现有api-ms-win-core-registry-l1-1-0.dll
,但 Reg API 里有两个可以读值,需要做个基本排序,按兼容性推测,使用 RegQueryValueExW 几率更高。
1 | // 老 API |
-
打开“无银第八哥”,按 Ctrl+E,打开
C:\Windows\System32\winver.exe
。 -
第一个需要尝试的断点是 RegQueryValueExW,输入
bm KERNELBASE!RegQueryValueExW
,然后 g,发现可以断下。 -
开始考虑“条件断点”,需要针对 lpValueName 判断是否为 “DisplayVersion”。lpValueName 为第二个参数,按照 x64 call,即为 rdx,所以编写
C:\devel\windbg\RegQueryValueExW.txt
代码如下:
1 | .if (@rdx != 0) { as /mu ${/v:ValueName} @rdx } .else { ad /q ${/v:ValueName} } |
然后,输入 bm KERNELBASE!RegQueryValueExW "$$<C:\\devel\\windbg\\RegQueryValueExW.txt"
,再 g,发现能断下:
1 | DisplayVersion |
- 额外地,可以返回(gu)看看(ub)调用方长啥样的:
1 | 0:000> gu |