Tuesday, 10 December 2013

Investigating Pool with Pool Data Structures

Pool is such as fundamental resource, and something which that can cause a few bugchecks if not handled properly. Here I'm going to explain some of the data structures used when looking at pool.

Firstly, we need to understand the different types of pool, and where they are used, the pool types are stored in a data structure of a enumeration called _POOL_TYPE.

The only values your going to need to be concerned with are Paged and Non-Paged Pool. As you most likely and should know, Paged Pool can be paged out onto the hard-drive and is susceptible to page faults, whereas, Non-Paged Pool must be resident in physical memory. Paged Pool can only be accessed at IRQL Level 2 or below, whereas, Non-Paged Pool is accessible at all IRQL Levels.

The other members of the enumeration are for internal use by Microsoft developers.

The _POOL_TYPE enumeration is actually a substructure of a larger data structure called _POOL_DESCRIPTOR.

 ListHeads is 512 element array of doubly linked free lists, which is the number of free allocation blocks, which can be used by drivers. Each block is associated with a _POOL_HEADER data structure.

TotalPages is the amount of pages of that pool type.

RunningAllocs and RunningDeAllocs is the amount of pages being allocated and deallocated.

PendingFrees are pages waiting to be freed.

Each descriptor is stored in an array called nt!PoolVector on single processor systems, however, on multiprocessor system it is stored in an array called nt!ExpNonPagedPoolDescriptor and nt!ExpPagedPoolDescriptor.

 Looking at the _POOL_HEADER data structure, I'll explain some of the fields, I haven't explained before, and some seen in previous blog posts:

Previous Size: The size of the previous allocation in the doubly linked list.

Pool Index: The index into the pool descriptor array.

Block Size: The size of the current allocation.

Pool Type: 0 means that the allocation is free, and if a allocation is present, then the hexadecimal number can be decrypted into PoolType and 2.

Pool Tag: The owner of the pool allocation.

The above example, is for a x86 system, however, there is an extra field present on x64 systems, which is the ProcessBilled field, this is a pointer to the process object (_EPROCESS) of the process which has been charged for the pool allocation, and is used for Quota Management. The ExAllocatePoolWithQuotaTag can be used here.

Depending upon the Pool Type, Quota Management is how amount Paged Pool and Non-Paged Pool that process is able to use. We can see these values with the !process extension.

The amount of Paged Pool and Non-Paged Pool a process can use, can be found in the Registry at HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management

1 comment: