MEMORY_ALLOCATION_DESCRIPTOR

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.

Memory Types

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.