> Windows Syscalls
ntoskrnl.exeT1622T1055.003T1106

NtGetContextThread

Recupera el contexto de registros de la CPU (estructura CONTEXT) de un hilo suspendido.

Prototipo

NTSTATUS NtGetContextThread(
  HANDLE    ThreadHandle,
  PCONTEXT  ThreadContext
);

Argumentos

NameTypeDirDescription
ThreadHandleHANDLEinHandle al hilo objetivo. Requiere acceso THREAD_GET_CONTEXT.
ThreadContextPCONTEXTin/outStruct CONTEXT específica de la arquitectura. ContextFlags (entrada) selecciona qué grupos de registros devolver; debe estar alineada a 16 bytes en x64.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070xE3win10-1507
Win10 16070xE6win10-1607
Win10 17030xE9win10-1703
Win10 17090xEAwin10-1709
Win10 18030xEBwin10-1803
Win10 18090xECwin10-1809
Win10 19030xEDwin10-1903
Win10 19090xEDwin10-1909
Win10 20040xF2win10-2004
Win10 20H20xF2win10-20h2
Win10 21H10xF2win10-21h1
Win10 21H20xF3win10-21h2
Win10 22H20xF3win10-22h2
Win11 21H20xF8win11-21h2
Win11 22H20xF9win11-22h2
Win11 23H20xF9win11-23h2
Win11 24H20xFBwin11-24h2
Server 20160xE6winserver-2016
Server 20190xECwinserver-2019
Server 20220xF7winserver-2022
Server 20250xFBwinserver-2025

Módulo del kernel

ntoskrnl.exeNtGetContextThread

APIs relacionadas

GetThreadContextWow64GetThreadContextNtSetContextThreadNtSuspendThreadRtlCaptureContext

Stub del syscall

4C 8B D1            mov r10, rcx
B8 FB 00 00 00      mov eax, 0xFB
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 estructura CONTEXT es específica de la arquitectura y voluminosa: en x64 ocupa 1232 bytes (CONTEXT) más un área XSTATE extendida cuyo tamaño depende de las capacidades de CPU habilitadas (los enclaves AVX-512 pueden superar 2,5 KB). El llamador debe establecer ContextFlags antes — CONTEXT_CONTROL (Rip, Rsp, EFlags), CONTEXT_INTEGER (Rax..R15), CONTEXT_SEGMENTS, CONTEXT_DEBUG_REGISTERS (DR0..DR7), CONTEXT_FLOATING_POINT, CONTEXT_XSTATE. El hilo debería estar suspendido; leer el contexto de un hilo en ejecución devuelve una instantánea que puede haber quedado obsoleta al recibirse.

Uso común por malware

La mitad de lectura de la primitiva de secuestro de hilo: suspender → obtener contexto → parchear Rip/Rsp → establecer contexto → reanudar. También usado por código anti-debug para leer DR0–DR3 de sus propios hilos y detectar breakpoints hardware instalados por un analista (`if (ctx.Dr0 || ctx.Dr1 || ctx.Dr2 || ctx.Dr3) abandonar();`). Algunas sandboxes marcan hilos con valores centinela en selectores de segmento no usados, y los packers los comprueban. Los BOF `inject` de Cobalt Strike, Sliver migrate, ScareCrow y la mayoría de variantes Early Bird APC pasan por aquí.

Oportunidades de detección

Por sí solo, NtGetContextThread tiene volumen moderado — depuradores, runtime .NET, profilers y manejadores de excepciones leen el contexto. Las lecturas entre procesos contra objetivos no depurados son mucho más raras; correlacionar la telemetría ETW Microsoft-Windows-Threat-Intelligence con el contexto de la relación entre procesos (padre/hijo, firmante). La detección más accionable es la *secuencia* NtSuspendThread → NtGetContextThread → NtSetContextThread → NtResumeThread en una ventana corta sobre un hilo remoto.

Ejemplos de syscalls directos

cHardware-breakpoint anti-debug self-check

// Detect analyst-set DR0..DR3 on our own primary thread.
CONTEXT ctx = { .ContextFlags = CONTEXT_DEBUG_REGISTERS };
if (NT_SUCCESS(NtGetContextThread(NtCurrentThread(), &ctx))) {
    if (ctx.Dr0 | ctx.Dr1 | ctx.Dr2 | ctx.Dr3) {
        // Hardware breakpoint installed -> exit silently.
        NtTerminateProcess(NtCurrentProcess(), 0);
    }
}

asmx64 stub (Win11 24H2)

NtGetContextThread PROC
    mov  r10, rcx              ; ThreadHandle
    mov  eax, 0FBh             ; Win11 24H2 SSN
    syscall
    ret
NtGetContextThread ENDP

rustRead RIP of suspended thread

use windows_sys::Win32::System::Diagnostics::Debug::*;

unsafe fn read_rip(h_thread: isize) -> Option<u64> {
    let mut ctx: CONTEXT = std::mem::zeroed();
    ctx.ContextFlags = CONTEXT_CONTROL_AMD64;   // RIP, RSP, SegCS, EFlags
    // Direct-syscall wrapper omitted for brevity.
    if nt_get_context_thread(h_thread, &mut ctx) >= 0 { Some(ctx.Rip) } else { None }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20