> Windows Syscalls
ntoskrnl.exeT1057T1055.003T1106

NtGetNextThread

Devuelve un handle al siguiente hilo dentro de un proceso recorriendo la lista de hilos del kernel.

Prototipo

NTSTATUS NtGetNextThread(
  HANDLE      ProcessHandle,
  HANDLE      ThreadHandle,
  ACCESS_MASK DesiredAccess,
  ULONG       HandleAttributes,
  ULONG       Flags,
  PHANDLE     NewThreadHandle
);

Argumentos

NameTypeDirDescription
ProcessHandleHANDLEinHandle al proceso cuyos hilos se enumeran. Requiere PROCESS_QUERY_INFORMATION.
ThreadHandleHANDLEinHandle al hilo devuelto previamente. NULL para iniciar la enumeración.
DesiredAccessACCESS_MASKinMáscara de acceso para el nuevo handle de hilo, p. ej. THREAD_GET_CONTEXT | THREAD_SET_CONTEXT.
HandleAttributesULONGinBanderas de atributos del handle. Habitualmente 0.
FlagsULONGinReservado. Pase 0.
NewThreadHandlePHANDLEoutRecibe el nuevo handle de hilo. STATUS_NO_MORE_ENTRIES indica el final de la lista.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070xE9win10-1507
Win10 16070xECwin10-1607
Win10 17030xEFwin10-1703
Win10 17090xF0win10-1709
Win10 18030xF1win10-1803
Win10 18090xF2win10-1809
Win10 19030xF3win10-1903
Win10 19090xF3win10-1909
Win10 20040xF8win10-2004
Win10 20H20xF8win10-20h2
Win10 21H10xF8win10-21h1
Win10 21H20xF9win10-21h2
Win10 22H20xF9win10-22h2
Win11 21H20xFEwin11-21h2
Win11 22H20xFFwin11-22h2
Win11 23H20xFFwin11-23h2
Win11 24H20x101win11-24h2
Server 20160xECwinserver-2016
Server 20190xF2winserver-2019
Server 20220xFDwinserver-2022
Server 20250x101winserver-2025

Módulo del kernel

ntoskrnl.exeNtGetNextThread

APIs relacionadas

NtGetNextProcessNtOpenThreadNtGetContextThreadNtSetContextThreadThread32FirstThread32Next

Stub del syscall

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

NtGetNextThread itera el ThreadListHead del EPROCESS abierto en ProcessHandle. Es el equivalente a nivel de hilo de NtGetNextProcess y tampoco tiene wrapper Win32 documentado — `Thread32First`/`Thread32Next` pasan por el snapshot de Toolhelp. Cada llamada devuelve un handle de kernel nuevo que el llamante debe cerrar (excepto cuando STATUS_NO_MORE_ENTRIES termina el recorrido). La función honra `PROCESS_QUERY_LIMITED_INFORMATION` si el llamante no necesita derechos más fuertes sobre el proceso, pero el acceso *hilo* deseado debe pedirse desde el principio — el handle no es fácilmente actualizable.

Uso común por malware

Se usa junto con NtGetNextProcess para enumerar cada hilo del sistema sin tocar Toolhelp32. La familia de inyección PoolParty (que abusa de los internals del thread pool) itera los hilos worker del pool con exactamente esta pareja de API para localizar un TP_WORKER objetivo que secuestrar. También lo usan implantes sigilosos de secuestro de hilo que eligen un hilo víctima, capturan su contexto con NtGetContextThread, modifican RIP y reanudan — todo sin llamar nunca a OpenThread por TID. Evitar `Thread32First/Next` es significativo porque Toolhelp crea una sección `_THSnapshot` visible para inspectores de tabla de handles.

Oportunidades de detección

Como NtGetNextProcess, este syscall tiene poco ruido de fondo — la mayoría de los enumeradores de procesos legítimos usan PSAPI o Toolhelp. Un pico de invocaciones de NtGetNextThread desde un único proceso no-sistema es sospechoso. Las consultas de threat-hunting que combinan ETW Microsoft-Windows-Kernel-Process (creación de hilo) con la *ausencia* de creaciones de sección Toolhelp esperadas pueden destapar este patrón. Sysmon Event ID 8 (CreateRemoteThread) solo se dispara en el secuestro consecutivo si se crea un hilo nuevo, no en secuestros por intercambio de contexto — así que la señal de alto valor es realmente NtSetContextThread contra un hilo ajeno inmediatamente después de la enumeración.

Ejemplos de syscalls directos

cStealth thread enumeration of a target process

// Walk every thread of a given process without Toolhelp32.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI *PNT_GET_NEXT_THREAD)(HANDLE, HANDLE, ACCESS_MASK, ULONG, ULONG, PHANDLE);

void EnumerateThreads(HANDLE hProcess) {
    HMODULE nt = GetModuleHandleA("ntdll.dll");
    PNT_GET_NEXT_THREAD pNtGetNextThread = (PNT_GET_NEXT_THREAD)GetProcAddress(nt, "NtGetNextThread");

    HANDLE hThread = NULL;
    HANDLE hNext   = NULL;
    while (pNtGetNextThread(hProcess, hThread, THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME,
                            0, 0, &hNext) == 0) {
        if (hThread) CloseHandle(hThread);
        hThread = hNext;
        // ... inspect TEB / GetThreadContext / hijack candidate ...
    }
    if (hThread) CloseHandle(hThread);
}

asmx64 direct stub (Win11 24H2, SSN 0x101)

NtGetNextThread PROC
    mov  r10, rcx
    mov  eax, 101h
    syscall
    ret
NtGetNextThread ENDP

Mapeos MITRE ATT&CK

Last verified: 2026-05-20