> Windows Syscalls
ntoskrnl.exeT1055T1106

NtCreateThread

Syscall historique de création de thread nécessitant une INITIAL_TEB construite à la main ; remplacé par NtCreateThreadEx.

Prototype

NTSTATUS NtCreateThread(
  PHANDLE            ThreadHandle,
  ACCESS_MASK        DesiredAccess,
  POBJECT_ATTRIBUTES ObjectAttributes,
  HANDLE             ProcessHandle,
  PCLIENT_ID         ClientId,
  PCONTEXT           ThreadContext,
  PINITIAL_TEB       InitialTeb,
  BOOLEAN            CreateSuspended
);

Arguments

NameTypeDirDescription
ThreadHandlePHANDLEoutReçoit le handle du thread nouvellement créé en cas de succès.
DesiredAccessACCESS_MASKinDroits d'accès pour le handle de thread retourné, typiquement THREAD_ALL_ACCESS.
ObjectAttributesPOBJECT_ATTRIBUTESinAttributs d'objet optionnels ; presque toujours NULL pour la création de thread.
ProcessHandleHANDLEinHandle vers le processus cible qui possédera le thread (PROCESS_CREATE_THREAD requis).
ClientIdPCLIENT_IDoutReçoit la paire (PID, TID) identifiant le thread nouvellement créé.
ThreadContextPCONTEXTinStructure CONTEXT entièrement remplie avec RIP/RSP pour le nouveau thread — état initial des registres fourni par l'appelant.
InitialTebPINITIAL_TEBinINITIAL_TEB construite à la main décrivant la pile utilisateur (base, limite, base d'allocation). La raison pour laquelle cette API est pénible.
CreateSuspendedBOOLEANinSi TRUE, le thread est créé en état suspendu et doit être repris avec NtResumeThread.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x4Ewin10-1507
Win10 16070x4Ewin10-1607
Win10 17030x4Ewin10-1703
Win10 17090x4Ewin10-1709
Win10 18030x4Ewin10-1803
Win10 18090x4Ewin10-1809
Win10 19030x4Ewin10-1903
Win10 19090x4Ewin10-1909
Win10 20040x4Ewin10-2004
Win10 20H20x4Ewin10-20h2
Win10 21H10x4Ewin10-21h1
Win10 21H20x4Ewin10-21h2
Win10 22H20x4Ewin10-22h2
Win11 21H20x4Ewin11-21h2
Win11 22H20x4Ewin11-22h2
Win11 23H20x4Ewin11-23h2
Win11 24H20x4Ewin11-24h2
Server 20160x4Ewinserver-2016
Server 20190x4Ewinserver-2019
Server 20220x4Ewinserver-2022
Server 20250x4Ewinserver-2025

Module noyau

ntoskrnl.exeNtCreateThread

APIs liées

CreateThreadCreateRemoteThreadRtlCreateUserThreadNtCreateThreadExNtResumeThread

Stub du syscall

4C 8B D1            mov r10, rcx
B8 4E 00 00 00      mov eax, 0x4E
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

NtCreateThread est la primitive originelle de création de thread, antérieure à Vista. Contrairement à son successeur NtCreateThreadEx, elle est non documentée dans les en-têtes publics et oblige l'appelant à construire à la main une INITIAL_TEB — décrivant la base, la limite et la base d'allocation de la pile — plus un CONTEXT entièrement rempli avec RIP/RSP. Le SSN `0x4E` est resté stable sur toutes les builds Windows 10 et Windows 11 supportées, ce qui est inhabituel et reflète le fait que Microsoft ne touche plus à cette surface. Le noyau l'implémente toujours pour compatibilité ascendante mais Win32 CreateThread, RtlCreateUserThread et NtCreateThreadEx passent tous aujourd'hui par NtCreateThreadEx.

Usage courant par les malwares

Utilisée par d'anciens outils d'injection antérieurs aux listes d'attributs de NtCreateThreadEx — certaines variantes de PassTheHash, les premières primitives de vol de token de Mimikatz et des alternatives historiques à CreateRemoteThread. Une petite portion de l'outillage offensif moderne choisit NtCreateThread précisément parce que peu d'EDR la hookent : l'API est si rarement utilisée par du code légitime que la couverture des éditeurs est inégale, en faisant un contournement de niche contre des piles de hooks userland naïves. La contrepartie est que l'appelant doit allouer et assembler une pile dans le processus cible avant d'émettre l'appel.

Opportunités de détection

ETW Microsoft-Windows-Threat-Intelligence émet des événements ThreadCreate depuis PspInsertThread, peu importe que le point d'entrée userland soit NtCreateThread ou NtCreateThreadEx — la télémétrie côté noyau est donc identique. Sysmon Event ID 8 (CreateRemoteThread) se déclenche également pour toute injection de thread cross-process. Le seul discriminant intéressant est en userland : un EDR qui ne hooke que ntdll!NtCreateThreadEx manquera les chemins passant par NtCreateThread. Les défenseurs doivent veiller à instrumenter les deux stubs et surveiller la rare combinaison NtCreateThread + ProcessHandle distant.

Exemples de syscalls directs

asmx64 direct stub

; Direct syscall stub for NtCreateThread (SSN 0x4E, Win10 1507+ through Win11 24H2)
NtCreateThread PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 4Eh          ; SSN
    syscall
    ret
NtCreateThread ENDP

cLegacy remote thread with hand-built INITIAL_TEB

// Caller must allocate stack in the target process and populate both CONTEXT and INITIAL_TEB.
typedef struct _INITIAL_TEB {
    PVOID PreviousStackBase;
    PVOID PreviousStackLimit;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID AllocatedStackBase;
} INITIAL_TEB, *PINITIAL_TEB;

SIZE_T stackSize = 0x10000;
PVOID  remoteStack = NULL;
NtAllocateVirtualMemory(hProcess, &remoteStack, 0, &stackSize,
                        MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

INITIAL_TEB teb = { 0 };
teb.StackBase          = (PBYTE)remoteStack + stackSize;
teb.StackLimit         = remoteStack;
teb.AllocatedStackBase = remoteStack;

CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_FULL;
ctx.Rip = (DWORD64)pShellcode;
ctx.Rsp = (DWORD64)teb.StackBase - 0x28;

HANDLE   hThread = NULL;
CLIENT_ID cid    = { 0 };
NtCreateThread(&hThread, THREAD_ALL_ACCESS, NULL, hProcess,
               &cid, &ctx, &teb, FALSE);

rustwindows-sys + naked syscall stub

// Cargo: windows-sys = "0.59"
use std::arch::asm;

#[unsafe(naked)]
unsafe extern "system" fn nt_create_thread_stub() {
    asm!(
        "mov r10, rcx",
        "mov eax, 0x4E",
        "syscall",
        "ret",
        options(noreturn),
    );
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20