> Windows Syscalls
ntoskrnl.exeT1055.004T1497T1106

NtWaitForMultipleObjects

Wartet auf bis zu MAXIMUM_WAIT_OBJECTS Dispatcher-Objekte mit WaitAny- oder WaitAll-Semantik.

Prototyp

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

Argumente

NameTypeDirDescription
CountULONGinAnzahl Handles im Handles-Array; muss 1..MAXIMUM_WAIT_OBJECTS (64) sein.
HandlesPHANDLEinZeiger auf ein Array wartebarer Dispatcher-Objekt-Handles, jedes mit SYNCHRONIZE-Zugriff.
WaitTypeWAIT_TYPEinWaitAll erfordert, dass alle Objekte signalisiert sind; WaitAny kehrt beim ersten zurück.
AlertableBOOLEANinTRUE erlaubt eingereihten User-APCs zu feuern und das Warten mit STATUS_USER_APC abzubrechen.
TimeoutPLARGE_INTEGERinOptionales Timeout in 100-ns-Einheiten; negativ = relativ, positiv = absolut, NULL = INFINITE.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
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

Kernel-Modul

ntoskrnl.exeNtWaitForMultipleObjects

Verwandte APIs

WaitForMultipleObjectsWaitForMultipleObjectsExMsgWaitForMultipleObjectsExNtWaitForSingleObjectNtSignalAndWaitForSingleObject

Syscall-Stub

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

Undokumentierte Hinweise

Dispatcht über `KeWaitForMultipleObjects` in ntoskrnl.exe. SSN `0x5B` ist über jeden Win10/11-Build stabil. Bei `WaitAny` zeigt der Returnwert `STATUS_WAIT_0..STATUS_WAIT_63` an, welches Handle signalisiert hat; bei `WaitAll` muss der Kernel den Zustand jedes Objekts atomar prüfen, weshalb `WaitAll` vergleichsweise teuer ist und `MAXIMUM_WAIT_OBJECTS` auf 64 begrenzt ist — der Dispatcher führt Waiter über einen Block fester Größe. Wie bei `NtWaitForSingleObject` öffnet das `Alertable`-Flag den Thread für die User-APC-Zustellung (mit Rückgabe `STATUS_USER_APC`).

Häufige Malware-Nutzung

Verwendet von Implants, die mehrere gleichzeitige Aufwachquellen unterhalten — typischerweise *(Timer-Event)* + *(Kill-Switch-Event)* + *(Netzwerk-Ready-Event)* —, damit der Beacon entweder auf abgelaufene Zeit oder auf einen Push des Control-Channels reagieren kann. Sleep-Mask-Varianten (Cronos, Zilean) warten auf das Verschlüsselungs-Stufen-Event plus ein Cancellation-Event, sodass der C2 einen laufenden Sleep-Zyklus unterbrechen kann. Manche Dropper warten auf mehrere Thread-Handles, um auf das Ende paralleler Entschlüsselungsstufen zu warten (WaitAll). Seltener dient ein alertable WaitAny auf handgebauten Handle-Arrays als flexiblerer APC-Empfangspunkt als Single-Object-Waits.

Erkennungs­möglichkeiten

Gleiche Einschränkungen wie bei `NtWaitForSingleObject`: zu häufig, um direkt zu alerten. Brauchbare Signale: alertable `WaitAny` über eine Handle-Menge, die ein privates benanntes Event enthält, gehalten von einem Prozess, dessen Code in nicht-gemapptem Speicher liegt; oder ein Thread, der routinemäßig auf >1 Handle wartet, eines davon ein Kernel-Transport-Layer-Objekt (\Device\Afd, Named Pipe, benanntes Event) plus ein synthetisiertes Timer-Event. Kernel-Mode-Handle-Tabelle gegen modulgebundene Thread-RIPs beim Sleep-Eintritt korrelieren.

Direkte Syscall-Beispiele

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.

MITRE ATT&CK-Mappings

Last verified: 2026-05-20