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

NtSetContextThread

Establece el contexto de registros de la CPU de un hilo — primitiva del kernel detrás del secuestro de hilo y la redirección de shellcode.

Prototipo

NTSTATUS NtSetContextThread(
  HANDLE    ThreadHandle,
  PCONTEXT  ThreadContext
);

Argumentos

NameTypeDirDescription
ThreadHandleHANDLEinHandle al hilo objetivo. Requiere acceso THREAD_SET_CONTEXT (y, idealmente, THREAD_SUSPEND_RESUME).
ThreadContextPCONTEXTinStruct CONTEXT específica de la arquitectura totalmente rellenada (1232 B en x64 más XSTATE opcional). ContextFlags selecciona qué grupos de registros se aplican.

IDs de syscalls por versión de Windows

Versión 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

Módulo del kernel

ntoskrnl.exeNtSetContextThread

APIs relacionadas

SetThreadContextWow64SetThreadContextNtGetContextThreadNtContinueNtQueueApcThreadAddVectoredExceptionHandler

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

Notas no documentadas

La mitad de alto impacto del par de contexto. El kernel valida el CONTEXT — CS debe ser un selector de modo usuario legal, EFlags tiene los bits reservados enmascarados y, en sistemas con CET (Windows 10 20H2+ con shadow stack HW), los ajustes de SSP/Ssp son saneados por KeVerifyContextRecord. La estructura CONTEXT es *específica de la arquitectura*: 1232 bytes en x64, 716 en x86 y ~880 en ARM64 — y Wow64SetThreadContext existe para puentear x86-sobre-x64 escribiendo el CONTEXT de 32 bits en el área WOW64 correspondiente. En builds con CET aplicado, escrituras a Rip que apunten a código no etiquetado CFG/IBT pueden fallar con STATUS_SET_CONTEXT_DENIED.

Uso común por malware

La primitiva canónica de inyección de shellcode (T1055.003 Thread Execution Hijacking). Secuencia completa: NtAllocateVirtualMemory(RWX) → NtWriteVirtualMemory(shellcode) → NtOpenThread → NtSuspendThread → NtGetContextThread → ctx.Rip = shellcode → NtSetContextThread → NtResumeThread. Variantes: (a) Early Bird — encolar una APC y luego fijar el contexto para dispararla en la primera espera alertable. (b) Hooking por breakpoint hardware — escribir DR0..DR3 con direcciones de funciones objetivo y DR7 con bits de control, luego manejar las #DB resultantes en un handler VEH para implementar hooks de userland invisibles a escáneres de hooks inline. (c) Intentos de bypass de CET abusando de XSTATE / campos del puntero de shadow stack.

Oportunidades de detección

NtSetContextThread sobre un hilo remoto es uno de los eventos de mayor señal en Windows. ETW Microsoft-Windows-Threat-Intelligence expone EtwTiLogSetContextThread con PID origen/destino y el nuevo Rip — alertar sobre cualquier llamada entre procesos cuyo nuevo Rip apunte a memoria privada (no respaldada por imagen). Los EDR suelen hookear en modo usuario vía parches inline a ntdll!NtSetContextThread; los syscalls directos eluden eso, pero TI-ETW permanece. CET / shadow stack en CPUs compatibles hace que la reescritura clásica de Rip sea menos fiable y aflora intentos fallidos como bugchecks de tipo KERNEL_SECURITY_CHECK_FAILURE si el atacante configura mal el nuevo contexto.

Ejemplos de syscalls directos

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

Mapeos MITRE ATT&CK

Last verified: 2026-05-20