> Windows Syscalls
ntoskrnl.exeT1055.004T1497T1106

NtWaitForMultipleObjects

Attend jusqu'à MAXIMUM_WAIT_OBJECTS objets dispatcher avec une sémantique WaitAny ou WaitAll.

Prototype

NTSTATUS NtWaitForMultipleObjects(
  ULONG          Count,
  PHANDLE        Handles,
  WAIT_TYPE      WaitType,
  BOOLEAN        Alertable,
  PLARGE_INTEGER Timeout
);

Arguments

NameTypeDirDescription
CountULONGinNombre de handles dans le tableau Handles ; doit être 1..MAXIMUM_WAIT_OBJECTS (64).
HandlesPHANDLEinPointeur vers un tableau de handles d'objets dispatcher waitables, chacun avec l'accès SYNCHRONIZE.
WaitTypeWAIT_TYPEinWaitAll exige que tous les objets soient signalés ; WaitAny retourne au premier signalé.
AlertableBOOLEANinTRUE autorise les APC utilisateur en file à s'exécuter et interrompre l'attente avec STATUS_USER_APC.
TimeoutPLARGE_INTEGERinTimeout optionnel en unités de 100 ns ; négatif = relatif, positif = absolu, NULL = INFINITE.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x5Bwin10-1507
Win10 16070x5Bwin10-1607
Win10 17030x5Bwin10-1703
Win10 17090x5Bwin10-1709
Win10 18030x5Bwin10-1803
Win10 18090x5Bwin10-1809
Win10 19030x5Bwin10-1903
Win10 19090x5Bwin10-1909
Win10 20040x5Bwin10-2004
Win10 20H20x5Bwin10-20h2
Win10 21H10x5Bwin10-21h1
Win10 21H20x5Bwin10-21h2
Win10 22H20x5Bwin10-22h2
Win11 21H20x5Bwin11-21h2
Win11 22H20x5Bwin11-22h2
Win11 23H20x5Bwin11-23h2
Win11 24H20x5Bwin11-24h2
Server 20160x5Bwinserver-2016
Server 20190x5Bwinserver-2019
Server 20220x5Bwinserver-2022
Server 20250x5Bwinserver-2025

Module noyau

ntoskrnl.exeNtWaitForMultipleObjects

APIs liées

WaitForMultipleObjectsWaitForMultipleObjectsExMsgWaitForMultipleObjectsExNtWaitForSingleObjectNtSignalAndWaitForSingleObject

Stub du syscall

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

Passe par `KeWaitForMultipleObjects` dans ntoskrnl.exe. La SSN `0x5B` est stable sur chaque build Win10/11. Avec `WaitAny`, la valeur de retour `STATUS_WAIT_0..STATUS_WAIT_63` identifie le handle ayant signalé ; avec `WaitAll`, le noyau doit vérifier atomiquement l'état de chaque objet, raison pour laquelle `WaitAll` est comparativement coûteux et `MAXIMUM_WAIT_OBJECTS` plafonné à 64 — le dispatcher traque les waiters via un bloc de taille fixe. Comme `NtWaitForSingleObject`, le flag `Alertable` ouvre le thread à la livraison d'APC utilisateur (renvoyant `STATUS_USER_APC`).

Usage courant par les malwares

Utilisé par des implants maintenant plusieurs sources de réveil simultanées — typiquement *(événement timer)* + *(événement kill-switch)* + *(événement réseau-prêt)* — pour que le beacon réagisse au temps écoulé ou à une commande du canal de contrôle. Les variantes de sleep-mask (Cronos, Zilean) attendent sur l'événement d'étape de chiffrement plus un événement d'annulation pour que le C2 puisse interrompre un cycle de sleep en cours. Certains droppers attendent sur plusieurs handles de threads pour attendre la fin d'étapes de déchiffrement parallèles (WaitAll). Plus rarement, un WaitAny alertable sur des tableaux de handles confectionnés sert de point de réception APC plus souple.

Opportunités de détection

Mêmes mises en garde que `NtWaitForSingleObject` : trop fréquent pour alerter brut. Signaux utiles : `WaitAny` alertable sur un ensemble de handles incluant un événement nommé privé détenu par un processus dont le code réside en mémoire non-backed ; ou un thread attendant régulièrement sur >1 handle dont l'un est un objet noyau de couche transport (\Device\Afd, named pipe, événement nommé) plus un timer event synthétisé. Corréler le contenu de la handle table en mode noyau avec les RIP des threads module-backed à l'entrée en sleep.

Exemples de syscalls directs

asmx64 direct stub

; Direct syscall stub for NtWaitForMultipleObjects (SSN 0x5B, stable across Win10/11)
NtWaitForMultipleObjects PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 5Bh          ; SSN
    syscall
    ret
NtWaitForMultipleObjects ENDP

cAlertable WaitAny on event + kill-switch

// Beacon wakes on either the sleep-timer event or an out-of-band cancel.
HANDLE waits[2] = { hSleepEvent, hCancelEvent };
NTSTATUS st = NtWaitForMultipleObjects(2, waits, WaitAny, TRUE, NULL);
if (st == STATUS_WAIT_0)       { /* normal beacon tick */ }
else if (st == STATUS_WAIT_1)  { /* operator told us to shut down */ }
else if (st == STATUS_USER_APC){ /* APC fired mid-wait */ }

cWaitAll on parallel decryption threads

// Spin up N threads to decrypt stage payload, then synchronize before execution.
HANDLE workers[4];
for (int i = 0; i < 4; i++)
    workers[i] = create_decrypt_worker(stage_slice(i));
NtWaitForMultipleObjects(4, workers, WaitAll, FALSE, NULL);
// All slices decrypted; safe to jump into stage.

Mappings MITRE ATT&CK

Last verified: 2026-05-20