> Windows Syscalls
ntoskrnl.exeT1057T1055.003T1106

NtGetNextThread

Retourne un handle vers le thread suivant d'un processus cible en parcourant la liste de threads du noyau.

Prototype

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

Arguments

NameTypeDirDescription
ProcessHandleHANDLEinHandle vers le processus dont les threads sont énumérés. Nécessite PROCESS_QUERY_INFORMATION.
ThreadHandleHANDLEinHandle vers le thread précédemment retourné. NULL pour démarrer l'énumération.
DesiredAccessACCESS_MASKinMasque d'accès pour le nouveau handle de thread, ex. THREAD_GET_CONTEXT | THREAD_SET_CONTEXT.
HandleAttributesULONGinDrapeaux d'attributs du handle. Généralement 0.
FlagsULONGinRéservé. Passez 0.
NewThreadHandlePHANDLEoutReçoit le nouveau handle de thread. STATUS_NO_MORE_ENTRIES marque la fin de la liste.

IDs de syscalls par version de Windows

Version 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

Module noyau

ntoskrnl.exeNtGetNextThread

APIs liées

NtGetNextProcessNtOpenThreadNtGetContextThreadNtSetContextThreadThread32FirstThread32Next

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

Notes non documentées

NtGetNextThread itère le ThreadListHead de l'EPROCESS ouvert dans ProcessHandle. C'est l'équivalent au niveau thread de NtGetNextProcess et n'a pas non plus de wrapper Win32 documenté — `Thread32First`/`Thread32Next` passent par le snapshot Toolhelp. Chaque appel retourne un handle noyau frais que l'appelant doit fermer (sauf quand STATUS_NO_MORE_ENTRIES termine le parcours). La fonction honore `PROCESS_QUERY_LIMITED_INFORMATION` si l'appelant n'a pas besoin de droits plus forts sur le processus, mais l'accès *thread* souhaité doit être demandé d'emblée — le handle n'est pas facilement améliorable.

Usage courant par les malwares

Utilisé avec NtGetNextProcess pour énumérer chaque thread du système sans toucher à Toolhelp32. La famille d'injection PoolParty (qui abuse des internals du thread pool) itère les threads worker du pool avec exactement ce couple d'API pour localiser un TP_WORKER cible à détourner. Également utilisé par les implants furtifs de détournement de thread qui choisissent un thread victime, capturent son contexte avec NtGetContextThread, modifient RIP, et reprennent — le tout sans jamais appeler OpenThread par TID. Éviter `Thread32First/Next` est significatif car Toolhelp crée une section `_THSnapshot` visible aux inspecteurs de table de handles.

Opportunités de détection

Comme NtGetNextProcess, ce syscall a peu de bruit de fond — la plupart des énumérateurs de processus légitimes utilisent PSAPI ou Toolhelp. Un pic d'invocations de NtGetNextThread depuis un seul processus non-système est suspect. Les requêtes de threat-hunting combinant l'ETW Microsoft-Windows-Kernel-Process (création de thread) avec l'*absence* des créations de section Toolhelp attendues peuvent révéler ce schéma. Sysmon Event ID 8 (CreateRemoteThread) ne se déclenche sur le détournement consécutif que si un nouveau thread est créé, pas sur les détournements par échange de contexte — le signal à haute valeur est en fait NtSetContextThread contre un thread étranger immédiatement après l'énumération.

Exemples de syscalls directs

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

Mappings MITRE ATT&CK

Last verified: 2026-05-20