Uninformed: Informative Information for the Uninformed

Vol 4» 2006.Jun


Retrieving Pool Ranges

For the purpose of enumerating pool memory it is unnecessary to enumerate the entire system address space. The system maintains a few global variables such as nt!MmPagedPoolStart, nt!MmPagedPoolEnd and related NonPagedPool variables that can be used in order to speed up a search and reduce the possibility of unnecessary false positives. Although these global variables are not exported, there are a couple ways in that they can be obtained.

The most reliable method on modern systems (Windows XP Service Pack 2 and up) is through the use of the KPCR->KdVersionBlock pointer located at fs:[0x34]. This points to a KDDEBUGGER_DATA64 structure which is defined in the Debugging Tools For Windows[8] SDK header file wdbgexts.h. This structure is commonly used by malicious software in order to gain access to non-exported global variables to manipulate the system.

A second method to obtain PagedPool values is to reference the per-session nt!_MM_SESSION_SPACE found at EPROCESS->Session. This contains information about the session owning the process, including its ranges and many other PagedPool related values shown here.

kd> dt nt!_MM_SESSION_SPACE
   +0x01c NonPagedPoolBytes : Uint4B
   +0x020 PagedPoolBytes   : Uint4B
   +0x024 NonPagedPoolAllocations : Uint4B
   +0x028 PagedPoolAllocations : Uint4B
   +0x044 PagedPoolMutex   : _FAST_MUTEX
   +0x064 PagedPoolStart   : Ptr32 Void
   +0x068 PagedPoolEnd     : Ptr32 Void
   +0x06c PagedPoolBasePde : Ptr32 _MMPTE
   +0x070 PagedPoolInfo    : _MM_PAGED_POOL_INFO
   +0x244 PagedPool        : _POOL_DESCRIPTOR

While enumerating the entire system address space is not preferable, it can still be used in situations where pool information cannot be obtained. The start of the system address space can be assumed to be any address above nt!MmHighestUserAddress. However, it would appear that an even safer assumption would be the address following the LARGE_PAGE where ntoskrnl.exe and hal.dll are mapped. This can be obtained by using any address exported by hal.dll and rounding up to the nearest large page.