NtAllocateUserPhysicalPages
Asigna páginas de memoria física para Address Windowing Extensions (AWE).
Prototipo
NTSTATUS NtAllocateUserPhysicalPages( HANDLE ProcessHandle, PULONG_PTR NumberOfPages, PULONG_PTR UserPfnArray );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle al proceso que será dueño de las páginas físicas. Habitualmente NtCurrentProcess(). |
| NumberOfPages | PULONG_PTR | in/out | En entrada: número de páginas físicas solicitadas. En salida: número realmente asignado. |
| UserPfnArray | PULONG_PTR | out | Arreglo proporcionado por el llamante que recibe un identificador opaco de page-frame por página asignada. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | 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 |
Módulo del kernel
APIs relacionadas
Stub del syscall
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
Notas no documentadas
Parte de la familia de API Address Windowing Extensions (AWE). AWE permite a un proceso reservar una ventana fija de direcciones virtuales y luego mapear y re-mapear bajo demanda páginas físicas arbitrarias dentro de ella — eludiendo por completo el working-set y el archivo de paginación de Windows. Los valores PFN opacos devueltos en UserPfnArray *no* son PFN crudos; son handles del lado kernel que solo pueden ser consumidos por NtMapUserPhysicalPages y NtFreeUserPhysicalPages en el mismo proceso. El llamante debe poseer **SeLockMemoryPrivilege** (habitualmente otorgado solo a LocalSystem y a cuentas de servicio configuradas explícitamente), lo que es la barrera práctica que mantiene AWE fuera del alcance de malware con pocos privilegios.
Uso común por malware
Tres abusos destacados. Primero, **escondrijo de código no-paginable**: las páginas asignadas vía AWE nunca se swapean al archivo de paginación, así que un payload mapeado vía NtMapUserPhysicalPages permanece fuera de pagefile.sys para siempre — frustrando la forense de disco muerto que recupera shellcode RWX desde un volcado de swap. Segundo, **amplificación de primitiva R/W de kernel**: combinado con un driver firmado vulnerable que exponga lectura/escritura arbitraria de memoria física, los PFN AWE permiten a una cadena de exploit aliasar el contenido de una página de kernel en una ventana user-mode, convirtiendo una lectura puntual en un mapeo persistente. Tercero, **evasión AV vía tipos VAD inusuales**: las asignaciones AWE aparecen como un subtipo VAD `VadAwe` que algunos escáneres ignoran. SeLockMemoryPrivilege es el cuello de botella; las muestras que necesitan AWE suelen pivotar por un servicio SYSTEM primero o encadenar una primitiva de suplantación de token que sobreviva al privilegio.
Oportunidades de detección
El uso de AWE fuera de SQL Server, Exchange, Oracle y un puñado de frameworks HPC es extremadamente raro. Detección por registro de eventos: vigile la adición de `SeLockMemoryPrivilege` a una cuenta no-servicio en la Local Security Policy, y los eventos de ajuste de token (Sysmon Event ID 4673 si la auditoría de subcategoría está habilitada) sobre `SeLockMemoryPrivilege`. Del lado kernel, el recorrido VAD aflorará entradas `VadAwe` en procesos inesperados (notepad.exe con una región AWE es enormemente anómalo). Los EDR con integración de escáner de memoria deberían tratar las reservas VirtualAlloc MEM_PHYSICAL en procesos no-base-de-datos como de alta severidad.
Ejemplos de syscalls directos
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 ENDPMapeos MITRE ATT&CK
Last verified: 2026-05-20