NtAllocateUserPhysicalPages
Allokiert physische Speicherseiten für Address Windowing Extensions (AWE).
Prototyp
NTSTATUS NtAllocateUserPhysicalPages( HANDLE ProcessHandle, PULONG_PTR NumberOfPages, PULONG_PTR UserPfnArray );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle auf den Prozess, der die physischen Seiten besitzen wird. Üblicherweise NtCurrentProcess(). |
| NumberOfPages | PULONG_PTR | in/out | Eingabe: Anzahl angeforderter physischer Seiten. Ausgabe: tatsächlich allokierte Anzahl. |
| UserPfnArray | PULONG_PTR | out | Vom Aufrufer bereitgestelltes Array, das je allokierter Seite einen opaken Page-Frame-Identifier empfängt. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x71 | win10-1507 |
| Win10 1607 | 0x71 | win10-1607 |
| Win10 1703 | 0x72 | win10-1703 |
| Win10 1709 | 0x72 | win10-1709 |
| Win10 1803 | 0x72 | win10-1803 |
| Win10 1809 | 0x72 | win10-1809 |
| Win10 1903 | 0x72 | win10-1903 |
| Win10 1909 | 0x72 | win10-1909 |
| Win10 2004 | 0x73 | win10-2004 |
| Win10 20H2 | 0x73 | win10-20h2 |
| Win10 21H1 | 0x73 | win10-21h1 |
| Win10 21H2 | 0x73 | win10-21h2 |
| Win10 22H2 | 0x73 | win10-22h2 |
| Win11 21H2 | 0x73 | win11-21h2 |
| Win11 22H2 | 0x73 | win11-22h2 |
| Win11 23H2 | 0x73 | win11-23h2 |
| Win11 24H2 | 0x75 | win11-24h2 |
| Server 2016 | 0x71 | winserver-2016 |
| Server 2019 | 0x72 | winserver-2019 |
| Server 2022 | 0x73 | winserver-2022 |
| Server 2025 | 0x75 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 75 00 00 00 mov eax, 0x75 F6 04 25 08 03 FE 7F 01 test byte ptr [0x7FFE0308], 1 75 03 jne short +3 0F 05 syscall C3 ret CD 2E int 2Eh C3 ret
Undokumentierte Hinweise
Teil der Address-Windowing-Extensions-(AWE-)API-Familie. AWE erlaubt einem Prozess, ein festes virtuelles Adressfenster zu reservieren und darin bedarfsweise beliebige physische Seiten zu mappen und remappen — unter völligem Umgehen von Working-Set und Pagefile. Die in UserPfnArray zurückgegebenen opaken PFN-Werte sind *keine* rohen PFNs; sie sind kernelseitige Handles, die nur von NtMapUserPhysicalPages und NtFreeUserPhysicalPages auf demselben Prozess konsumiert werden können. Der Aufrufer muss **SeLockMemoryPrivilege** halten (in der Regel nur LocalSystem und explizit konfigurierten Service-Konten gewährt), was die praktische Hürde ist, die AWE für niedrigprivilegierte Malware außer Reichweite hält.
Häufige Malware-Nutzung
Drei nennenswerte Missbräuche. Erstens, **nicht-pagebares Code-Versteck**: AWE-allokierte Seiten werden nie in die Pagefile geswappt, ein über NtMapUserPhysicalPages gemappter Payload bleibt also für immer aus pagefile.sys heraus — und schlägt damit Dead-Disk-Forensik, die RWX-Shellcode aus Swap-Dumps rekonstruiert. Zweitens, **Kernel-R/W-Primitiv-Verstärkung**: kombiniert mit einem verwundbaren signierten Treiber, der beliebige physische Speicher-Read/Write exponiert, lassen die AWE-PFNs eine Exploit-Kette Kernel-Seiteninhalte in ein User-Mode-Fenster aliasen — aus einem Einmal-Read wird ein persistentes Mapping. Drittens, **AV-Evasion über ungewöhnliche VAD-Typen**: AWE-Allokationen erscheinen als `VadAwe`-VAD-Subtyp, den manche Scanner ignorieren. SeLockMemoryPrivilege ist der Engpass; Samples, die AWE brauchen, pivotieren meist erst über einen SYSTEM-Dienst oder verketten eine Token-Impersonation-Primitive, die das Privileg überlebt.
Erkennungsmöglichkeiten
AWE-Nutzung außerhalb von SQL Server, Exchange, Oracle und einer Handvoll HPC-Frameworks ist extrem selten. Event-Log-basierte Erkennung: das Hinzufügen von `SeLockMemoryPrivilege` zu einem Nicht-Service-Konto in der Local Security Policy überwachen, ebenso Token-Adjustment-Events (Sysmon Event ID 4673 bei aktiviertem Subcategory-Auditing) auf `SeLockMemoryPrivilege`. Kernelseitig fördert der VAD-Walk `VadAwe`-Einträge in unerwarteten Prozessen zutage (notepad.exe mit einer AWE-Region ist hochgradig anomal). EDRs mit Memory-Scanner-Integration sollten MEM_PHYSICAL-VirtualAlloc-Reservierungen in Nicht-Datenbank-Prozessen als hochkritisch werten.
Direkte Syscall-Beispiele
cAWE allocation gated on SeLockMemoryPrivilege
// Enable SeLockMemoryPrivilege, then allocate physical pages and reserve a
// virtual address window for mapping.
#include <windows.h>
BOOL EnableLockMemoryPrivilege(void) {
HANDLE hTok;
TOKEN_PRIVILEGES tp;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTok)) return FALSE;
LookupPrivilegeValueA(NULL, "SeLockMemoryPrivilege", &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL ok = AdjustTokenPrivileges(hTok, FALSE, &tp, 0, NULL, NULL) && GetLastError() == ERROR_SUCCESS;
CloseHandle(hTok);
return ok;
}
void awe_alloc(SIZE_T pages) {
EnableLockMemoryPrivilege();
ULONG_PTR request = pages;
ULONG_PTR *pfn = (ULONG_PTR*)HeapAlloc(GetProcessHeap(), 0, pages * sizeof(ULONG_PTR));
if (AllocateUserPhysicalPages(GetCurrentProcess(), &request, pfn)) {
SIZE_T window = pages * 4096;
PVOID view = VirtualAlloc(NULL, window,
MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE);
MapUserPhysicalPages(view, request, pfn);
// 'view' now aliases the physical pages; remap on demand.
}
}asmx64 direct stub (Win11 24H2, SSN 0x75)
NtAllocateUserPhysicalPages PROC
mov r10, rcx
mov eax, 75h
syscall
ret
NtAllocateUserPhysicalPages ENDPMITRE ATT&CK-Mappings
Last verified: 2026-05-20