Geoff Chappell, Software Analyst
The MEMORY_ALLOCATION_DESCRIPTOR structure is how the loader describes to the kernel what memory has been found and which of it is already in use for what purpose.
There is one structure for each memory block. The structures are provided as a double-linked list, linked through the ListEntry member. The head is the MemoryDescriptorListHead member of the LOADER_PARAMETER_BLOCK structure whose address the loader passes to the kernel as the latter’s one argument for initialisation. Until the kernel completes its initialisation, it keeps the address in the exported KeLoaderBlock variable, which means the whole list of memory blocks can be easily inspected not just with a debugger but by device drivers.
Though the MEMORY_ALLOCATION_DESCRIPTOR structure is undocumented, it is stable up to and including Windows Vista. In 32-bit builds, it is stable even to Windows 10. In 64-bit builds, however, Windows 7 supports physical memory above 16TB and therefore widens two members. Names, types and offsets given below are from Microsoft’s symbol files for Windows Vista and higher. Symbol files for earlier versions do not have type information for this structure.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
LIST_ENTRY ListEntry; |
|
0x08 | 0x10 |
TYPE_OF_MEMORY MemoryType; |
|
0x0C | 0x14 |
ULONG BasePage; |
before 6.1 |
0x18 |
ULONG_PTR BasePage; |
6.1 and higher | |
0x10 | 0x18 |
ULONG PageCount; |
before 6.1 |
0x20 |
ULONG_PTR PageCount; |
6.1 and higher |
The size of a MEMORY_ALLOCATION_DESCRIPTOR is 0x14 bytes in 32-bit builds and either 0x20 or 0x28 bytes in 64-bit builds depending on the version.
What use a memory block has already been put to, if any, is indicated by the TYPE_OF_MEMORY enumeration, which allows more possibilities in later versions. Most types are ancient and some are very old. Exactly which versions they each date from is, in the absence of type information in symbol files from before Windows Vista, something of a guess (which, if only for now, I don’t even attempt before Windows 2000).
Numerical Value | Symbolic Name | Versions |
---|---|---|
0x00 |
LoaderExceptionBlock |
|
0x01 |
LoaderSystemBlock |
|
0x02 |
LoaderFree |
|
0x03 |
LoaderBad |
|
0x04 |
LoaderLoadedProgram |
|
0x05 |
LoaderFirmwareTemporary |
|
0x06 |
LoaderFirmwarePermanent |
|
0x07 |
LoaderOsloaderHeap |
|
0x08 |
LoaderOsloaderStack |
|
0x09 |
LoaderSystemCode |
|
0x0A |
LoaderHalCode |
|
0x0B |
LoaderBootDriver |
|
0x0C |
LoaderConsoleInDriver |
|
0x0D |
LoaderConsoleOutDriver |
|
0x0E |
LoaderStartupDpcStack |
|
0x0F |
LoaderStartupKernelStack |
|
0x10 |
LoaderStartupPanicStack |
|
0x11 |
LoaderStartupPcrPage |
|
0x12 |
LoaderStartupPdrPage |
|
0x13 |
LoaderRegistryData |
|
0x14 |
LoaderMemoryData |
|
0x15 |
LoaderNlsData |
|
0x16 |
LoaderSpecialMemory |
|
0x17 |
LoaderBBTMemory |
5.0 and higher |
0x18 |
LoaderReserve |
5.0 and higher |
0x19 |
LoaderXIPRom |
5.1 and higher |
0x1A |
LoaderHalCachedMemory |
5.1 and higher |
0x1B |
LoaderLargePageFiller |
5.1 and higher |
0x1C |
LoaderErrorLogMemory |
6.1 and higher |
0x1D |
LoaderVsmMemory |
10.0 and higher |
0x1E |
LoaderFirmwareCode |
10.0 and higher |
0x1F |
LoaderFirmwareData |
10.0 and higher |
0x20 |
LoaderFirmwareReserved |
10.0 and higher |
0x21 |
LoaderEnclaveMemory |
10.0 from Version 1511, and higher |
Whatever the verson, the formal enumeration continues one value further to a LoaderMaximum.