> Windows Syscalls
ntoskrnl.exeT1055.003T1055.004T1106

NtSetContextThread

Définit le contexte des registres CPU d'un thread — primitive noyau derrière le détournement de thread et la redirection de shellcode.

Prototype

NTSTATUS NtSetContextThread(
  HANDLE    ThreadHandle,
  PCONTEXT  ThreadContext
);

Arguments

NameTypeDirDescription
ThreadHandleHANDLEinHandle vers le thread cible. Requiert l'accès THREAD_SET_CONTEXT (et idéalement THREAD_SUSPEND_RESUME).
ThreadContextPCONTEXTinStructure CONTEXT spécifique à l'architecture entièrement renseignée (1232 o sur x64 plus XSTATE optionnel). ContextFlags sélectionne les groupes de registres appliqués.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x16Fwin10-1507
Win10 16070x178win10-1607
Win10 17030x17Ewin10-1703
Win10 17090x181win10-1709
Win10 18030x183win10-1803
Win10 18090x184win10-1809
Win10 19030x185win10-1903
Win10 19090x185win10-1909
Win10 20040x18Bwin10-2004
Win10 20H20x18Bwin10-20h2
Win10 21H10x18Bwin10-21h1
Win10 21H20x18Dwin10-21h2
Win10 22H20x18Dwin10-22h2
Win11 21H20x195win11-21h2
Win11 22H20x198win11-22h2
Win11 23H20x198win11-23h2
Win11 24H20x19Awin11-24h2
Server 20160x178winserver-2016
Server 20190x184winserver-2019
Server 20220x193winserver-2022
Server 20250x19Awinserver-2025

Module noyau

ntoskrnl.exeNtSetContextThread

APIs liées

SetThreadContextWow64SetThreadContextNtGetContextThreadNtContinueNtQueueApcThreadAddVectoredExceptionHandler

Stub du syscall

4C 8B D1            mov r10, rcx
B8 9A 01 00 00      mov eax, 0x19A
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

La moitié à fort impact de la paire de contexte. Le noyau valide le CONTEXT — CS doit être un sélecteur user-mode légal, EFlags a ses bits réservés masqués, et sur les systèmes CET (Windows 10 20H2+ avec shadow stack matériel) les ajustements de SSP/Ssp sont assainis par KeVerifyContextRecord. La structure CONTEXT est *spécifique à l'architecture* : 1232 octets en x64, 716 en x86, ~880 en ARM64 — et Wow64SetThreadContext existe pour faire le pont x86-sur-x64 en écrivant le CONTEXT 32 bits dans la zone WOW64 correspondante. Sur les builds avec CET appliqué, les écritures de Rip pointant sur du code non marqué CFG/IBT peuvent échouer avec STATUS_SET_CONTEXT_DENIED.

Usage courant par les malwares

La primitive canonique d'injection de shellcode (T1055.003 Thread Execution Hijacking). Séquence complète : NtAllocateVirtualMemory(RWX) → NtWriteVirtualMemory(shellcode) → NtOpenThread → NtSuspendThread → NtGetContextThread → ctx.Rip = shellcode → NtSetContextThread → NtResumeThread. Variantes : (a) Early Bird — file une APC puis pose le contexte pour la déclencher à la première attente alertable. (b) Hooking par breakpoint matériel — écrire DR0..DR3 avec les adresses de fonctions cibles et DR7 avec les bits de contrôle, puis traiter les #DB dans un handler VEH pour implémenter des hooks userland invisibles aux scanners de hooks inline. (c) Tentatives de contournement CET abusant des champs XSTATE / shadow-stack pointer.

Opportunités de détection

NtSetContextThread sur un thread distant est l'un des événements les plus porteurs de signal de Windows. ETW Microsoft-Windows-Threat-Intelligence expose EtwTiLogSetContextThread avec PID source/cible et le nouveau Rip — alerter sur tout appel inter-processus dont le nouveau Rip pointe sur de la mémoire privée (non image-backed). Les EDR hookent couramment en user-mode via des patches inline sur ntdll!NtSetContextThread ; les syscalls directs y échappent, mais TI-ETW reste. CET / shadow stack sur CPU compatibles rendent la réécriture classique de Rip moins fiable et font remonter les tentatives échouées en bugchecks de type KERNEL_SECURITY_CHECK_FAILURE si l'attaquant mal-configure le nouveau contexte.

Exemples de syscalls directs

cClassic SetThreadContext shellcode hijack

// Assumes shellcode already written to remoteShellcode in target process.
CONTEXT ctx = { .ContextFlags = CONTEXT_FULL };
NtSuspendThread(hThread, NULL);
NtGetContextThread(hThread, &ctx);
ctx.Rip = (DWORD64)remoteShellcode;     // redirect on resume
NtSetContextThread(hThread, &ctx);
NtResumeThread(hThread, NULL);

cHardware-breakpoint hook install

// Install a userland hook on a target function via DR0 + #DB VEH handler.
CONTEXT ctx = { .ContextFlags = CONTEXT_DEBUG_REGISTERS };
NtGetContextThread(hTargetThread, &ctx);
ctx.Dr0 = (DWORD64)pTargetFn;
ctx.Dr7 = (1ULL << 0)  /* L0 */ |
          (0ULL << 16) /* RW0=00 execute */ |
          (0ULL << 18) /* LEN0=00 1-byte */;
NtSetContextThread(hTargetThread, &ctx);
// AddVectoredExceptionHandler then catches EXCEPTION_SINGLE_STEP at pTargetFn.

rustx64 stub (Win11 24H2)

use std::arch::asm;

#[unsafe(naked)]
unsafe extern "system" fn nt_set_context_thread_stub() {
    asm!(
        "mov r10, rcx",
        "mov eax, 0x19A",        // Win11 24H2 SSN
        "syscall",
        "ret",
        options(noreturn),
    );
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20