分类 调试 下的文章

最近要求我在升级过程中跟踪一个问题。问题归结为在安装过程中捕获打开特定注册表服务项的Microsoft组件。像这样的问题经常需要实时调试来实时捕获注册表访问。我本可以在RegOpenKeyExW()上设置一个断点,并检查传递到函数中的每个请求的键,但是考虑到RegOpenKeyExW()是一个使用率很高的代码路径,所以这个方法非常耗时。此方法包括在函数上设置断点,等待插入,检查第二个参数(lpSubKey)是否与所需的注册表项(string)匹配,如果该项不匹配,则单击“g”。在找到包含我所需密钥的调用之前,我可以重复这些步骤100次。我想找个办法,只有在我的Key被碰过的时候才会设置“中断访问”。我们遇到了一个类似的问题,需要在可能有数百个文件正在使用时捕获文件系统函数处理特定文件。那么,如何实现这种类型的调试所需的自动化呢?答案是调试器脚本。

让我们来看看Windows的一个例子资源管理器使用这种方法。在这个场景中,我们将尝试捕捉资源管理器正在打开HKEY U LOCAL U MACHINE\SYSTEM\Setup键。Windows资源管理器每秒打开多个键,因此重点是在将此特定键传递给RegOpenKeyEx()时“插入”,而不必手动遍历传递给函数的数百个可能的键。

1、确定有问题的函数

根据MSDN,RegOpenKeyEx定义如下,我们对第二个参数感兴趣,因为它包含键的名称。

系统会遇到随机错误检查,内存损坏。有趣的是,腐败有一个非常特殊的模式——它看起来像是一个PFN地址,在这个过程中,标志被随机地放置在页面表页面的几个地方。内存管理器永远不会做这种事情,我怀疑驱动程序正在编辑用户页表页,这是不应该做的。

让我们看看堆栈:

kd>kb*** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr Args to Child
f15b1308
80523096 c00862d8 10c5b000 00000000 nt!MiDeletePte+0x198f15b13d080519776 000001d8 10d20fff 00000000 nt!MiDeleteVirtualAddresses+0x164f15b13ec 805b1d74 10c20000 10d20fff f15b14a4 nt!MiDeleteFreeVm+0x20f15b148c 8054060c ffffffff 049c6aa8 049c6ab0 nt!NtFreeVirtualMemory+0x42ef15b148c 7c90eb94 ffffffff 049c6aa8 049c6ab0 nt!KiFastCallEntry+0xfc03e4a398 7c90da54 7c8209b3 ffffffff 049c6aa8 ntdll!KiFastSystemCallRet
03e4a39c 7c8209b3 ffffffff 049c6aa8 049c6ab0 ntdll
!NtFreeVirtualMemory+0xc

我最近注意到的一个趋势是,在尝试KB304101(PoolUsageMaximum)之后,MmSt标签的使用率仍然很高,这是一种趋势。内存管理器将这些池分配用于节对象原型pte。通常只有两种选择:1)升级到64位平台,或2)减小卷的大小。但我们可能想知道哪些映射文件正在使用这个内存。这是如何做到的。从!memusage开始。

5: kd> !memusage

loading PFN database

loading (
100%complete)

Compiling memory usage data (
99%Complete).

Zeroed:
19073 ( 76292kb)

Free:
0 ( 0kb)

Standby:
1468824 (5875296kb)

Modified:
368 ( 1472kb)

ModifiedNoWrite:
1927 ( 7708kb)

Active
/Valid: 605772 (2423088kb)

Transition:
0 ( 0kb)

Bad:
0 ( 0kb)

Unknown:
0 ( 0kb)

TOTAL:
2095964 (8383856kb)

Building kernel map

Finished building kernel map

Scanning PFN database
- (100% complete)