> Windows Syscalls
ntoskrnl.exeT1055T1055.002T1620

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

NameTypeDirDescription
ProcessHandleHANDLEinHandle al proceso objetivo. Use NtCurrentProcess() ((HANDLE)-1) para sí mismo.
BaseAddressPVOID*in/outPuntero a la dirección base solicitada. NULL deja que el kernel elija. Actualizado al retornar.
ZeroBitsULONG_PTRinNúmero de bits altos en cero en BaseAddress. Típicamente 0.
RegionSizePSIZE_Tin/outPuntero al tamaño deseado, redondeado al límite de página al retornar.
AllocationTypeULONGinBanderas de asignación. MEM_COMMIT | MEM_RESERVE es la combinación más común.
ProtectULONGinConstante de protección de memoria, p. ej. PAGE_READWRITE, PAGE_EXECUTE_READWRITE.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 19090x18win10-1909
Win10 20040x18win10-2004
Win10 20H20x18win10-20h2
Win10 21H10x18win10-21h1
Win10 21H20x18win10-21h2
Win10 22H20x18win10-22h2
Win11 21H20x18win11-21h2
Win11 22H20x18win11-22h2
Win11 23H20x18win11-23h2
Win11 24H20x18win11-24h2
Server 20190x18winserver-2019
Server 20220x18winserver-2022
Server 20250x18winserver-2025

Módulo del kernel

ntoskrnl.exeNtAllocateVirtualMemory

APIs relacionadas

VirtualAllocVirtualAllocExNtAllocateVirtualMemoryExNtProtectVirtualMemoryNtWriteVirtualMemoryNtFreeVirtualMemory

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 ENDP

cHell'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