NtAllocateVirtualMemory
Reserva, confirma o ambas en una región de memoria virtual de un proceso objetivo.
Prototipo
NTSTATUS NtAllocateVirtualMemory( HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle al proceso objetivo. Use NtCurrentProcess() ((HANDLE)-1) para sí mismo. |
| BaseAddress | PVOID* | in/out | Puntero a la dirección base solicitada. NULL deja que el kernel elija. Actualizado al retornar. |
| ZeroBits | ULONG_PTR | in | Número de bits altos en cero en BaseAddress. Típicamente 0. |
| RegionSize | PSIZE_T | in/out | Puntero al tamaño deseado, redondeado al límite de página al retornar. |
| AllocationType | ULONG | in | Banderas de asignación. MEM_COMMIT | MEM_RESERVE es la combinación más común. |
| Protect | ULONG | in | Constante de protección de memoria, p. ej. PAGE_READWRITE, PAGE_EXECUTE_READWRITE. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1909 | 0x18 | win10-1909 |
| Win10 2004 | 0x18 | win10-2004 |
| Win10 20H2 | 0x18 | win10-20h2 |
| Win10 21H1 | 0x18 | win10-21h1 |
| Win10 21H2 | 0x18 | win10-21h2 |
| Win10 22H2 | 0x18 | win10-22h2 |
| Win11 21H2 | 0x18 | win11-21h2 |
| Win11 22H2 | 0x18 | win11-22h2 |
| Win11 23H2 | 0x18 | win11-23h2 |
| Win11 24H2 | 0x18 | win11-24h2 |
| Server 2019 | 0x18 | winserver-2019 |
| Server 2022 | 0x18 | winserver-2022 |
| Server 2025 | 0x18 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 18 00 00 00 mov eax, 0x18 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
El número de syscall de NtAllocateVirtualMemory ha permanecido notablemente estable desde Windows 10 1909 hasta Windows 11 24H2 — `0x18`. Esto *no* ocurre con muchos syscalls adyacentes (p. ej. NtCreateThreadEx), por lo que la resolución dinámica vía Hell's Gate o Halo's Gate se prefiere a los números codificados al objetivo varios builds. La función despacha a través de KiSystemServiceCopyEnd → MmAllocateVirtualMemory dentro de ntoskrnl.exe.
Uso común por malware
Fundamental para casi todo loader de shellcode: asignar memoria RW o RWX en el proceso actual o remoto, copiar el payload y luego cambiar la protección con NtProtectVirtualMemory. Usado por el spawn de beacon de Cobalt Strike, implantes Sliver, inyección clásica y la mayoría de los droppers comerciales. Combinado con NtWriteVirtualMemory + NtCreateThreadEx forma la cadena canónica equivalente a CreateRemoteThread por syscalls directos.
Oportunidades de detección
Por sí solo, NtAllocateVirtualMemory es *extremadamente* común en software legítimo y no es una señal útil. Lo que importa es *cómo* y *dónde* se invoca: asignaciones RWX, asignaciones en procesos remotos, y secuencias cortas RW→RX→ejecutar. Los EDR hookean NtAllocateVirtualMemory en ntdll.dll; los syscalls directos eluden ese hook pero dejan artefactos visibles desde el kernel (entradas VAD, eventos ETW Threat Intelligence, callbacks PsSetCreateProcessNotifyRoutineEx para creación de hilo remoto). Sysmon Event ID 8 (CreateRemoteThread) y Event ID 10 (ProcessAccess con VM_OPERATION/VM_WRITE) son la telemetría blue-team más útil — se disparan sobre las *consecuencias* de la asignación, no la asignación en sí.
Ejemplos de syscalls directos
asmx64 direct stub
; Direct syscall stub for NtAllocateVirtualMemory (SSN 0x18, Win10 1909+)
NtAllocateVirtualMemory PROC
mov r10, rcx ; syscall convention
mov eax, 18h ; SSN
syscall
ret
NtAllocateVirtualMemory ENDPcHell's Gate dynamic lookup
// Resolve SSN dynamically from ntdll export at runtime — survives KB updates.
DWORD GetSyscallNumber(PVOID pNtFunction) {
BYTE* p = (BYTE*)pNtFunction;
if (p[0] == 0x4C && p[1] == 0x8B && p[2] == 0xD1 && p[3] == 0xB8) {
return *(DWORD*)(p + 4);
}
return 0;
}
// usage
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
DWORD ssn = GetSyscallNumber(GetProcAddress(hNtdll, "NtAllocateVirtualMemory"));rustwindows-sys + naked asm
// Cargo: windows-sys = "0.59" (Win32_Foundation, Win32_System_Memory)
use std::arch::asm;
#[unsafe(naked)]
unsafe extern "system" fn nt_alloc_virtual_memory_stub() {
asm!(
"mov r10, rcx",
"mov eax, 0x18",
"syscall",
"ret",
options(noreturn),
);
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20