非分页池的消耗

我最近在处理一个问题,服务器在几天内耗尽了NonPagedPool。通常,我们只需要使用像PoolMon这样的工具来识别有问题的pool标记,然后使用本文中的方法找到使用该pool标记的驱动程序。然而,让这个案例有趣的是pool标记,而且我们无法使用常规方法识别驱动程序。你一会儿就会明白我的意思了。支持给我提供了服务器处于状态时的内核转储,这就是我发现的。
让我们先看看虚拟内存的使用情况:

2: kd> !vm

*** Virtual Memory Usage ***

Physical Memory: 851420 ( 3405680 Kb)

Page File: \??\C:\pagefile.sys

Current: 3584000 Kb Free Space: 3568552 Kb

Minimum: 3584000 Kb Maximum: 3584000 Kb

Available Pages: 573277 ( 2293108 Kb)

ResAvail Pages: 800628 ( 3202512 Kb)

Locked IO Pages: 1067 ( 4268 Kb)

Free System PTEs: 25102 ( 100408 Kb)

Free NP PTEs: 335 ( 1340 Kb)

Free Special NP: 0 ( 0 Kb)

Modified Pages: 22 ( 88 Kb)

Modified PF Pages: 22 ( 88 Kb)

NonPagedPool Usage: 31369 ( 125476 Kb) ß Very high

NonPagedPool Max: 31986 ( 127944 Kb)

********** Excessive NonPaged Pool Usage *****

PagedPool 0 Usage: 19071 ( 76284 Kb)

PagedPool 1 Usage: 735 ( 2940 Kb)

PagedPool 2 Usage: 747 ( 2988 Kb)

PagedPool 3 Usage: 720 ( 2880 Kb)

PagedPool 4 Usage: 746 ( 2984 Kb)

PagedPool Usage: 22019 ( 88076 Kb)

PagedPool Maximum: 38912 ( 155648 Kb)

********** 3 pool allocations have failed **********

所以我们可以看到NPP的使用率非常高,因为服务器使用的是/3GB开关,默认情况下NPP限制在128MB。我们需要确定哪些池标记与高NPP使用率相关:

2: kd> !poolused /t2 2

Sorting by NonPaged Pool Consumed

Pool Used:

NonPaged Paged

Tag Allocs Used Allocs Used

None 246479 50827424 0 0 call to ExAllocatePool

MmCm 1198 18462512 0 0 Calls made to MmAllocateContiguousMemory , Binary: nt!mm

很有趣,所以这个有问题的标签是“None”。这意味着这些分配是通过调用函数ExAllocatePool而不是ExAllocatePoolWithTag来完成的。ExAllocatePool已过时,不应再使用。
现在,我需要找出哪个驱动程序在调用这个函数。首先,我需要知道ExAllocatePool住在哪里:

2: kd> x nt!ExAllocatePool

e0894d1f nt!ExAllocatePool

Next, I need to search all the drivers to see which one is importing this function:

2: kd> !for_each_module s-d @#Base @#End e0894d1f

f50b8058 e0894d1f e0828e04 e089b708 e084011b .M..............

看起来可疑地像导入表,让我们看看:

2: kd> dps f50b8058

f50b8058 e0894d1f nt!ExAllocatePool

f50b805c e0828e04 nt!_wcsnicmp

f50b8060 e089b708 nt!ExFreePoolWithTag

f50b8064 e083e30a nt!KeInitializeEvent
...

是的,那是导入表。您还可以通过检查标题(用!dh在模块基址并查找“Import Address Table Directory”)。
如您所见,我们只有一个驱动程序导入ExAllocatePool。让我们看看这是哪个驱动程序:

2: kd> !lmi f50b8058

Loaded Module Info: [f50b8058]

Module: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}

Base Address: f50b3000

Image Name: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}.sys

为了保护罪犯,我已经从上面显示的模块信息中删除了有罪的标识符。有趣的是,驱动程序名是一个GUID,而这个驱动程序不存在于磁盘上。这是因为驱动程序是在其父程序加载时动态创建的。
将软件包被删除,服务器又恢复了正常。

posted on 2020-09-18 07:51  活着的虫子  阅读(524)  评论(1编辑  收藏  举报

导航