> Windows Syscalls
ntoskrnl.exeT1055T1055.002T1620

NtAllocateVirtualMemory

Réserve, valide ou les deux une région de mémoire virtuelle dans un processus cible.

Prototype

NTSTATUS NtAllocateVirtualMemory(
  HANDLE    ProcessHandle,
  PVOID    *BaseAddress,
  ULONG_PTR ZeroBits,
  PSIZE_T   RegionSize,
  ULONG     AllocationType,
  ULONG     Protect
);

Arguments

NameTypeDirDescription
ProcessHandleHANDLEinHandle vers le processus cible. Utilisez NtCurrentProcess() ((HANDLE)-1) pour soi-même.
BaseAddressPVOID*in/outPointeur vers l'adresse de base demandée. NULL laisse le noyau choisir. Mis à jour au retour.
ZeroBitsULONG_PTRinNombre de bits de poids fort à zéro dans BaseAddress. Typiquement 0.
RegionSizePSIZE_Tin/outPointeur vers la taille souhaitée, arrondie à la page supérieure au retour.
AllocationTypeULONGinDrapeaux d'allocation. MEM_COMMIT | MEM_RESERVE est la combinaison la plus courante.
ProtectULONGinConstante de protection mémoire, ex. PAGE_READWRITE, PAGE_EXECUTE_READWRITE.

IDs de syscalls par version de Windows

Version 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

Module noyau

ntoskrnl.exeNtAllocateVirtualMemory

APIs liées

VirtualAllocVirtualAllocExNtAllocateVirtualMemoryExNtProtectVirtualMemoryNtWriteVirtualMemoryNtFreeVirtualMemory

Stub du 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

Notes non documentées

Le numéro de syscall de NtAllocateVirtualMemory est resté remarquablement stable de Windows 10 1909 jusqu'à Windows 11 24H2 — `0x18`. Ce n'est *pas* le cas de nombreux syscalls adjacents (ex. NtCreateThreadEx), ce qui explique pourquoi la résolution dynamique via Hell's Gate ou Halo's Gate est préférée aux numéros codés en dur lorsqu'on cible plusieurs builds. La fonction passe par KiSystemServiceCopyEnd → MmAllocateVirtualMemory dans ntoskrnl.exe.

Usage courant par les malwares

Fondamental pour pratiquement tout loader de shellcode : allouer de la mémoire RW ou RWX dans le processus courant ou distant, copier le payload, puis changer la protection avec NtProtectVirtualMemory. Utilisé par le spawn de beacon Cobalt Strike, les implants Sliver, l'injection classique, et la plupart des droppers du commerce. Combiné à NtWriteVirtualMemory + NtCreateThreadEx, il forme la chaîne canonique équivalente à CreateRemoteThread en syscalls directs.

Opportunités de détection

Pris isolément, NtAllocateVirtualMemory est *extrêmement* courant en logiciel légitime et n'est pas un signal exploitable. Ce qui compte, c'est *comment* et *où* il est appelé : allocations RWX, allocations dans des processus distants, séquences courtes RW→RX→exécution. Les EDR hookent NtAllocateVirtualMemory dans ntdll.dll ; les syscalls directs contournent ce hook mais laissent des artefacts visibles côté noyau (entrées VAD, événements ETW Threat Intelligence, callbacks PsSetCreateProcessNotifyRoutineEx pour la création de thread distant). Sysmon Event ID 8 (CreateRemoteThread) et Event ID 10 (ProcessAccess avec VM_OPERATION/VM_WRITE) sont les télémétries blue-team les plus utiles — elles se déclenchent sur les *conséquences* de l'allocation, pas l'allocation elle-même.

Exemples de syscalls directs

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),
    );
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20