系统会遇到随机错误检查,内存损坏。有趣的是,腐败有一个非常特殊的模式——它看起来像是一个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+0x198 f15b13d0 80519776 000001d8 10d20fff 00000000 nt!MiDeleteVirtualAddresses+0x164 f15b13ec 805b1d74 10c20000 10d20fff f15b14a4 nt!MiDeleteFreeVm+0x20 f15b148c 8054060c ffffffff 049c6aa8 049c6ab0 nt!NtFreeVirtualMemory+0x42e f15b148c 7c90eb94 ffffffff 049c6aa8 049c6ab0 nt!KiFastCallEntry+0xfc 03e4a398 7c90da54 7c8209b3 ffffffff 049c6aa8 ntdll!KiFastSystemCallRet 03e4a39c 7c8209b3 ffffffff 049c6aa8 049c6ab0 ntdll!NtFreeVirtualMemory+0xc
以下是虚拟地址的页表条目:
kd> !pte 10c5b000 VA 10c5b000 PDE at 00000000C0600430 PTE at 00000000C00862D8 contains 000000003FC6F867 contains 0000000015E0086F pfn 3fc6f ---DA--UWEV pfn 15e00 ---DA-TUWEV
这表明值15e0086f未正确放入页表页中。此错误值对应于通过调用MmAllocatePagesForMdl分配的范围的直写映射。
c00862d0 00000000 00000000 15e0086f 00000000 c00862e0 00000000 00000000 00000000 00000000 c00862f0 00000000 00000000 00000000 00000000 c0086300 00000000 00000000 00000000 00000000 c0086310 00000000 00000000 00000000 00000000 c0086320 00000000 00000000 00000000 00000000 c0086330 00000000 00000000 00000000 00000000 c0086340 00000000 00000000 00000000 00000000 c0086350 00000000 00000000 15e0086f 00000000 c0086360 00000000 00000000 00000000 00000000 c0086370 00000000 00000000 00000000 00000000 c0086380 00000000 00000000 00000000 00000000 c0086390 00000000 00000000 00000000 00000000 c00863a0 00000000 00000000 00000000 00000000 c00863b0 00000000 00000000 00000000 00000000 c00863c0 00000000 00000000 00000000 00000000 c00863d0 00000000 00000000 00000000 00000000 c00863e0 00000000 00000000 00000000 00000000 c00863f0 00000000 00000000 00000000 00000000 c0086400 00000000 00000000 00000000 00000000 c0086410 00000000 00000000 00000000 00000000 c0086420 00000000 00000000 00000000 00000000 c0086430 00000000 00000000 00000000 00000000 c0086440 00000000 00000000 00000000 00000000 c0086450 00000000 00000000 00000000 00000000 c0086460 15e0086f 00000000 00000000 00000000 c0086470 00000000 00000000 00000000 00000000 c0086480 00000000 00000000 00000000 00000000 c0086490 00000000 00000000 00000000 00000000 c00864a0 00000000 00000000 00000000 00000000 c00864b0 00000000 00000000 00000000 00000000 c00864c0 00000000 00000000 00000000 00000000 c00864d0 00000000 00000000 00000000 00000000 c00864e0 15e0086f 00000000 00000000 00000000 c00864f0 00000000 00000000 00000000 00000000 c0086500 00000000 00000000 00000000 00000000 c0086510 00000000 00000000 00000000 00000000 c0086520 00000000 00000000 00000000 00000000 c0086530 00000000 00000000 00000000 00000000 c0086540 00000000 00000000 00000000 00000000 c0086550 00000000 00000000 00000000 00000000 c0086560 15e0086f 00000000 00000000 00000000 c0086570 00000000 00000000 00000000 00000000 c0086580 00000000 00000000 00000000 00000000 c0086590 00000000 00000000 00000000 00000000 c00865a0 00000000 00000000 00000000 00000000 c00865b0 00000000 00000000 00000000 00000000 c00865c0 00000000 00000000 00000000 00000000 c00865d0 00000000 00000000 00000000 00000000 c00865e0 00000000 00000000 00000000 00000000 c00865f0 00000000 00000000 00000000 00000000 c0086600 00000000 00000000 00000000 00000000 c0086610 00000000 00000000 00000000 00000000 c0086620 00000000 00000000 00000000 00000000 c0086630 00000000 00000000 00000000 00000000 c0086640 00000000 00000000 00000000 00000000 c0086650 00000000 00000000 00000000 00000000 c0086660 00000000 00000000 15e0086f 00000000 c0086670 00000000 00000000 00000000 00000000 c0086680 00000000 00000000 00000000 00000000 c0086690 00000000 00000000 00000000 00000000 c00866a0 00000000 00000000 00000000 00000000 c00866b0 00000000 00000000 00000000 00000000 c00866c0 00000000 00000000 00000000 00000000 c00866d0 00000000 00000000 00000000 00000000 c00866e0 00000000 00000000 15e0086f 00000000 c00866f0 00000000 00000000 00000000 00000000 c0086700 00000000 00000000 00000000 00000000 c0086710 00000000 00000000 00000000 00000000 c0086720 00000000 00000000 00000000 00000000 c0086730 00000000 00000000 00000000 00000000 c0086740 00000000 00000000 00000000 00000000 c0086750 00000000 00000000 00000000 00000000 c0086760 00000000 00000000 15e0086f 00000000 c0086770 00000000 00000000 00000000 00000000 c0086780 00000000 00000000 00000000 00000000 c0086790 00000000 00000000 00000000 00000000 c00867a0 00000000 00000000 00000000 00000000 c00867b0 00000000 00000000 00000000 00000000 c00867c0 00000000 00000000 00000000 00000000 c00867d0 00000000 00000000 00000000 00000000 c00867e0 00000000 00000000 00000000 00000000 kd> !pfn 15e00 PFN 00015E00 at address 81BCA800 flink 00000000 blink / share count 00000001 pteaddress 000AF001 reference count 0002 Cached color 0 restore pte 00000080 containing page FFEDCB Active RW ReadInProgress WriteInProgress
在引用计数为2的页面上,驱动程序还有一个未完成的调用MmProbeAndLockPages调用。认为这个pfn值不正确,我决定搜索这个值,看看能找到什么。
kd> s -d 80000000 l?7fffffff 00015e00 8022d534 00015e00 0001f190 00041d50 0001f140 .^......P...@... 86cacbf4 00015e00 0000cd1c 0000cc27 0000cc08 .^......'....... 86e25cdc 00015e00 0a130005 e56c6946 00000000 .^......Fil.....
我找到了一些条目,但是中间的条目看起来可能是MDL分配。所以我核实了一下:
kd> !pool 86cacbf4 2 Pool page 86cacbf4 region is Nonpaged pool *86cacbd0 size: 80 previous size: 28 (Allocated) *Mdl Pooltag Mdl : Io, Mdls
是的,这是MDL,让我们检查一下:
kd> dt nt!_MDL 86cacbd8 +0x000 Next : (null) +0x004 Size : 32 +0x006 MdlFlags : 138 +0x008 Process : (null) +0x00c MappedSystemVa : 0x00004000 +0x010 StartVa : 0xf7baa000 +0x014 ByteCount : 0xfff +0x018 ByteOffset : 0
请注意,页面15e00位于MDL的页面列表中。
kd> dd 86cacbd8+1c 86cacbf4 00015e00 0000cd1c 0000cc27 0000cc08 86cacc04 0000cc09 0000cc0a 0000cc0b 0000cbec 86cacc14 0000cbed 0000cbee 0000cbef 0000cbd0 86cacc24 0000cbd1 0000cbd2 0000cbd3 0000cbd4 86cacc34 0000cbd5 0000cbd6 00000000 00000000 86cacc44 00000000 00000000 00000000 00010010
接下来,我想看看是否可以找到一个驱动程序,它可能引用了这个MDL,我找到了两个:
kd> s -d 80000000 l?7fffffff 86cacbd8 86f9c6a0 86cacbd8 0000003d 00000000 0000636a ....=.......jc.. 86fc7e68 86cacbd8 00000001 00000001 00000000 ................
现在让我们看看谁拥有这些
kd> !pool 86f9c6a0 2 Pool page 86f9c6a0 region is Nonpaged pool *86f9c618 size: d8 previous size: 30 (Allocated) *Crpt Pooltag Crpt : Memory corruption driver kd> !pool 86fc7e68 2 Pool page 86fc7e68 region is Nonpaged pool *86fc7e00 size: 98 previous size: 40 (Allocated) *Crpt Pooltag Crpt : Memory corruption driver
这给了我们一个很有说服力的可能性,这个司机有过错。所以现在您可能会问,“为什么这个问题是在应用了ServicePack2之后才出现的?”默认情况下,安装Server Pack 2时,支持它的系统上会启用数据执行保护(DEP)。对DEP的支持在PAE内核中,它使用额外的位来描述页表条目。在这次崩溃中,解决方案是禁用DEP,直到驱动程序被纠正为止。驱动程序错误地使用了内存映射,忽略了页码中的额外位,并通过写入错误的页导致内存损坏。