Explore the Windows 2000XP POOL Distribution Process (http:webcrazy.yeah.net)

xiaoxiao2021-03-06  38

Explore the Windows 2000 / XP POOL Allocation Process

Webcrazy (http://webcrazy.yeah.net)

For Driver writers, the most invalidation is the use of various memory buffers (talk to the buffer, you may think of concepts such as MDL, in fact, MDL is only organized for the POOL-specified Pool Number specified by Startva). . In the user state, the memory of the small block is involved in Heap, Windows 2000 / XP provides the same mechanism in the core state for the memory requirements of this part of the core module, which is different from the user state, we will call this called POOL (Memory pool). Loosing the kernel module and some nature of the user module, such as pool can not be accessed directly by the user module, and the Heap is the process. The difference between the system is related. Pool and HEAP have some difference between the organization management, this article focuses on Pool Organizations conducted some light analysis.

We know that Windows is generally Pool divided into two categories: NonpagedPool and a scalar page (PagedPool). Depending on whether Aligned, whether MUSTSUCCESS, etc., the part is distinguished. Pool_Type definition from NTDDK.H, pool_type is an enum definition, which is always an even number (such as NonpagedPool 0), and PagedPool is 1). Usually we allocate a memory area by kernel routine ExallocatePool (Withtag), they accept a pool_type and a distributed size parameter, when we allocate greater than Page_Size from Pool (more accurate should be greater than Page_Size-0x10, in x86 When Page_Size is 4K), the assigned result is always the page pair (at the page boundary), and if less than Page_Size (more accurate, it should be less than Page_Size-0x10), allocation is always in a page and always It is 8-byte alignment, which is critical to the narrative below.

Windows has reserved different virtual memory areas for Pool allocation for non-paged pools and paneling pools. The kernel variable MMPAGEDPoolStart is specified for the scope of the paging pool, which is usually started from 0xE1000000. The space of the non-paging pool consists of two areas, and the conventional area begins with MmnonPageDpoolStart, and other EXPANSION regions, which are specified by MnonPakeDpoolendStart and MmnonPaultPoolend, for Driver developers, we are generally easily determined from these sections to determine non-paged pools Sub-pool.

For the paging pool and the non-paged pool, Windows is organized by a pool_descriptor, respectively (actually Windows usually there will be other pool_descriptors, such as the session space session, etc., this article does not discuss), the definition is as follows:

0x000 PoolType: _Pool_Type

0x004 poolindex: uint4b

0x008 RunningAllocs: uint4b

0x00c RunningdeDeallocs: uint4b

0x010 Totalpages: uint4b

0x014 TotalbigPages: uint4b

0x018 Threshold: uint4b

0x01c LockAddress: ptr32 void

0x020 PendingFrees: ptr32 void

0x024 PendingFreedepth: int4b

0x028 Listheads: [512] _LIST_ENTRY

For the two pool_descriptors of the non-paged pool and the paging pool, the system variable poolvector array organization, we can use poolVector [pool_type & 1] to get the corresponding pool_descriptor. Note that there is a 512-length bidirectional linked list at the end of POOL_DEScriptor. For Pool less than 1 page, because we allocated Pool is aligned, the assigned result is always in page 1, so the array of bidirectional linked lists for 512 is used, each of which will be The sporadic size of the pages that have been assigned in the system is organized into a two-way linked list of 8 to 4096. For a continuous idle area in page 1, the system is always in the largest linked list as much as possible, for example, for the 16-byte area, always placed in Listheads [1], not to insert two nodes to Listhead [0]. With such a list, the system is easy to manage Pool allocation. For situations greater than Page_Size, the system will also involve reassign the SYSTEM PTE, which will be described again after I discuss with a 4k byte space allocated.

Before discussing these small pieces, we must first understand the difference between Lookaside, Lookaside and the usual pool, which is only used to assign fixed-size memory pools. EXInitializenPagedLookasidelist is used to initialize lookaside, and the related DDK documentation is referred to in the routine that allocates the memory pool from the LookasidElist. Since SPINLOCK is not considered, the space allocated is much better than the usual POOL allocation is made. We can understand this way, usually, when we use ExinitializenPagedLookasidelist to initialize lookaside, you can provide allocate_function and free_function parameters for allocating large block memory areas (system default using ExallocatePool and ExfreePool), then sporadic allocation. In view of the speed of the speed, the Windows executive generates a LOOKASIDE to NonPagedPool from 8 to 256 bytes to NonPagedPool, located in Kprcb (I am in Windows XP Build 2600 in Windows XP Build 2600). 0x598 In 0x698), for AllocatePool less than (0x20 8 bytes, 256 bytes), the execution function ExallocatePool allocates directly from these Lookaside. As for the Lookaside's depth, the memory manager will be adjusted using KiaDjustLookAsidedEPTH.

Now we consider the POOL assignment between 0x100 (256 bytes) and 0x1000 (4K, Page_SIZE), suppose we assign 0xB18 bytes, actually allocate 0xB20 bytes, and 8 bytes of 8 bytes are pool_header Structure, used to manage Pool, the structure of Pool_Header is as follows:

0x000 Previoussize: POS 0, 9 BITS

0x000 PoolIndex: POS 9, 7 BITS

0x002 Blocksize: POS 0, 9 BITS

0x002 PoolType: POS 9, 7 BITS 0x000 Ulong1: uint4b

0x004 ProcessBilled: Ptr32_eprocess

0x004 pooltag: uint4b

0x004 AllocatorBackTraceIndex: UINT2B

0x006 PoolTaghash: UINT2B

For this range of pool, the system will find the corresponding pool_descriptor based on poolVector, and we can easily calculate the system will look for the two-way linked list of PoolDescriptor.listheads [0x164] because 0xB20 / 8 is 0x164. If this list is not empty, the system will get a node of this list, which represents a size of 0xB20, if this is an empty list, the system will locate the next two-way linked list after 0x165 until found A size between 0xB28 and 0x1000 between 0xB28 and 0x1000. At this time, the remaining space is allocated, and the system will insert the corresponding size list_entry (here considering fragment merge), waiting for the next assignment. Of course, if there is still a space that meets the corresponding conditions, the system will use MiallocatePoolPages to assign all page memory pools.

If it is executed to miallocatePoolpages, it first determines whether the assigned paging pool or is a non-paging pool. If it is a non-paging pool, the system will first look for MmnonPakedPoolFreelisthead, like the Listheads of PoolDescriptor, MmnonPakedPoolFreelisthead is also a two-way linked list, the number of elements is 4 The idle list of non-paged pools representing 1 to 4, respectively (4 or more idle spaces are also stored in the fourth array, which requires additional judgment, which is not described here. This is a linked list maintained by the system memory manager. MiallocatePoolPages will first get an idle list from this, if found, and then modify the PFN database. If you don't find it, you need to reserve System PTE, which I will continue to talk in later discussion. For the paging pool, it is another case. She involves another important structure of the system: mm_paged_pool_info, defined as follows:

0x000 PagedPoolAlCationMap: PTR32 _RTL_BITMAP

0x004 endofpagedpoolbitmap: PTR32 _RTL_BITMAP

0x008 PagedPoollargesessionAllocationMap: PTR32 _RTL_BITMAP

0x00c FirstPteforPagedPool: PTR32_MMPTE

0x010 lastpteforPagedPool: PTR32_MMPTE

0x014 NextPdeforPagedPoolExpansion: PTR32_MMPTE

0x018 PagedPoolhint: uint4b

0x01c PagedPoolCommit: uint4b

0x020 AllocatedPagedPool: UINT4B

FirstpteforPagedPool is the first PTE location of the PagedPool virtual address, usually the PTE location of MmpagedPoolStart (0xe1000000), that is, (0xE1000000 >> a) & 0x3fffc-0x40000000 = 0xc0384000 (Please refer to "small discussion Windows NT / 2000 paging mechanism "), We can easily verify this by MM_PAGED_POOL_INFO points to the kernel variable MmpageDpoolInfo. The same is also easy to get values ​​via MmpageDpooledPool for LastPTeforPageDpool. MiallocatePoolPages is all assigned to several RTL_bitmap, etc., etc. RTL_bitmap I introduced in "Discussion Windows 2000 / XP Pagefile Organization", I also said that using RTLFINDSETBITSANDCLEAR and RTLSetBits et al. To find the corresponding idle bit, the same miallocatepoolpages also uses this method. Next, we will talk about more than 4K, for allocation greater than Page_Size (0x1000 bytes, actually greater than 0xFF0 bytes, POOL_BLOCK_HEADER Take up 16 bytes), will call miallocatePoolPages, which will call with the above description. For the paging pool, the system is initialized in the initialization phase, which is the initialization of PTE, which is to PageFile.SYS, although because the size of PageFile.sys can be expanded automatically, this also involves the initialization of Mmpte_Software after the extension (PTE pointing to the page file, See "Discussion Windows 2000 / XP PageFile Management"), the rest of the RTL_bitmap bit is operational, and the FAULT operation that appears in these pages is the task of INT E (X86). So I only focus on the non-paged pool.

For non-paged pool can be obtained directly from the page MmNonPagedPoolFreeListHead situation we have already been discussed, but if we can not MmNonPagedPoolFreeListHead obtained from the above-mentioned page, the system must call MiReserveSystemPtes to apply System PTE, then call MiReserveAlignedSystemPtes, retained the System After PTE (Get the number of pages from allocation), we must also call MichargeCommitmentCantexpand's assignment and then involve the operation of the PFN database.

MIRESERVEALIGNEDSYSTEMPTES is used to retain System PTE, which is actually the process of assigning system virtual addresses. He finds the idle virtual address specified by MMFirstFreesystemPte (for example, 0xfb2b6000), get this address relative to the PTE of MMSystemptebase (in Windows XP, the value of MMSystemptebase is 0xc0000000, this result is 0xC03ECAD8), according to this The number of idle pages stored in the PTE address (do not know why, Microsoft exists this data to this), assigns a virtual address from the tail of the virtual address. Note that this is the tail address, so that you don't have to update MMFirstFREESYSTEMPTE, the number of idle pages stored in the PTE location requires only reduced number of pages without replacing the location.

After getting the virtual address, we must allocate the actual physical address to meet this call. This is usually done by MichargeCommitmentCantexpand, if necessary, he will call Miremove Anpage, then populate the SYSTEM PTE that is just retained to complete such an allocation work. In fact, I have basically introduced ExalkatePoolWithtag (ExallocatePool just pass a TAG called 'None' ExallocatePoolwithTAG) to explain most. As for the release of Pool, that is, ExfreePool process, it is not difficult to analyze it after these knowledge. ExallocatePoolwithtag This execution body has more complicated relative to other routines. It is necessary to consider many of the factors such as Align or MUSTSUCCESS for pool_type. In addition, it is also necessary to consider Pool Track (ExpinsertPoolTracker) because of the need to debug, such as Driver Verifier or Poolmon, and SPECIAL POOL, etc. I just say these basic processes, but this may have a lot of bad understandings, involving a lot of knowledge I have written previously about PFN Database, PTE, etc., let alone I have this part of the content. The level of master is not to tell you about it, this article is a throwing brick.

转载请注明原文地址:https://www.9cbs.com/read-62127.html

New Post(0)