> Windows Syscalls
ntoskrnl.exeT1055T1106

NtCreateIoCompletion

Erzeugt einen I/O-Completion-Port — die Kernel-Queue, die Threadpool-Arbeitsauslieferung, asynchrone I/O-Benachrichtigung und (bei PoolParty) injizierte Work-Items trägt.

Prototyp

NTSTATUS NtCreateIoCompletion(
  PHANDLE             IoCompletionHandle,
  ACCESS_MASK         DesiredAccess,
  POBJECT_ATTRIBUTES  ObjectAttributes,
  ULONG               Count
);

Argumente

NameTypeDirDescription
IoCompletionHandlePHANDLEoutErhält das neue Completion-Port-Handle bei Erfolg.
DesiredAccessACCESS_MASKinAngeforderter Zugriff — IO_COMPLETION_ALL_ACCESS (0xF0003) gibt query+modify+synchronize.
ObjectAttributesPOBJECT_ATTRIBUTESinOptionale OBJECT_ATTRIBUTES — üblicherweise NULL; benannte Ports liegen unter \BaseNamedObjects.
CountULONGinConcurrency-Hinweis: maximale Anzahl Threads, die der Kernel gleichzeitig dequeuen lässt. 0 bedeutet NumberOfProcessors.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070xA0win10-1507
Win10 16070xA2win10-1607
Win10 17030xA5win10-1703
Win10 17090xA6win10-1709
Win10 18030xA7win10-1803
Win10 18090xA7win10-1809
Win10 19030xA8win10-1903
Win10 19090xA8win10-1909
Win10 20040xACwin10-2004
Win10 20H20xACwin10-20h2
Win10 21H10xACwin10-21h1
Win10 21H20xADwin10-21h2
Win10 22H20xADwin10-22h2
Win11 21H20xAFwin11-21h2
Win11 22H20xB0win11-22h2
Win11 23H20xB0win11-23h2
Win11 24H20xB2win11-24h2
Server 20160xA2winserver-2016
Server 20190xA7winserver-2019
Server 20220xAFwinserver-2022
Server 20250xB2winserver-2025

Kernel-Modul

ntoskrnl.exeNtCreateIoCompletion

Verwandte APIs

CreateIoCompletionPortGetQueuedCompletionStatusPostQueuedCompletionStatusNtSetIoCompletionNtRemoveIoCompletionNtRemoveIoCompletionExNtCreateWorkerFactory

Syscall-Stub

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

I/O-Completion-Ports sind die hochperformante asynchrone Benachrichtigungs-Primitive, die fast jeden Windows-Server trägt: IIS, SQL Server, .NET-ThreadPool, Win32-Threadpool, RPC, WinHTTP und die meisten Netzwerk-Stacks Dritter. `CreateIoCompletionPort` in kernel32 ist ein dünner Wrapper, der NtCreateIoCompletion beim ersten Sichten eines unbekannten Handles aufruft. Das Kernel-Objekt speichert eine doppelt verkettete Queue von KQUEUE-Einträgen, ein Concurrency-Limit und eine Liste aktuell zugeordneter Threads (via NtAssociateWaitCompletionPacket oder in NtRemoveIoCompletion gestapelt). Der `Count`-Parameter ist eine weiche Obergrenze, kein hartes Limit — zusätzliche Threads dürfen dequeuen, wenn bestehende blockieren.

Häufige Malware-Nutzung

Für sich genommen meist harmlos — jede moderne Anwendung erzeugt diese. Die PoolParty-Relevanz ist strukturell: Completion-Ports sind die Queue-Hälfte der Worker-Factory-Primitive. Ein Angreifer erzeugt einen (im eigenen Prozess oder per Duplikation in ein Opfer), verdrahtet ihn via NtCreateWorkerFactory mit einer Worker Factory und liefert dann via NtSetIoCompletion gefälschte Work-Items. Der Port ist auch die Queue, die NtWaitForWorkViaWorkerFactory leert. Manche Sleep-Obfuskations-Gadgets (Ekko, foliage-artige Techniken) missbrauchen Completion-Port-Waits, um das I/O-Profil eines harmlosen Idle-Servers zu imitieren.

Erkennungs­möglichkeiten

Erzeugung ist zu häufig, um zu alarmieren. Das interessante Signal ist die *Handle-Topologie*: ein in Prozess A erzeugter Completion-Port, via NtDuplicateObject in Prozess B dupliziert und dort sofort an eine Worker Factory gebunden, ist ein Lehrbuch-PoolParty-Muster. Das Verfolgen von Handle-Duplikationen von `IoCompletion`-Objekten über Prozessgrenzen via ObRegisterCallbacks (oder ein Kernel-Callback, der PsSetCreateThreadNotifyRoutine hookt, um die gebundene Queue des neuen Threads zu inspizieren) liefert hochwertige Abdeckung. ETW Microsoft-Windows-Kernel-IoCompletion bietet begrenzte Sichtbarkeit.

Direkte Syscall-Beispiele

cPlain port for a threadpool

HANDLE hIoCompletion = NULL;
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
NTSTATUS s = NtCreateIoCompletion(
    &hIoCompletion,
    IO_COMPLETION_ALL_ACCESS,
    &oa,
    0);                                  // 0 = NumberOfProcessors concurrency
if (!NT_SUCCESS(s)) return s;

cPoolParty plumbing — port + remote duplicate

// Create locally, then duplicate INTO the victim — the victim's worker factory
// will be bound to it in the next step.
HANDLE hLocal = NULL, hRemote = NULL;
OBJECT_ATTRIBUTES oa; InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
NtCreateIoCompletion(&hLocal, IO_COMPLETION_ALL_ACCESS, &oa, 1);
NtDuplicateObject(NtCurrentProcess(), hLocal,
                  hVictim, &hRemote,
                  0, 0, DUPLICATE_SAME_ACCESS);

asmx64 direct stub (Win11 24H2 SSN 0xB2)

NtCreateIoCompletion PROC
    mov  r10, rcx
    mov  eax, 0B2h
    syscall
    ret
NtCreateIoCompletion ENDP

MITRE ATT&CK-Mappings

Last verified: 2026-05-20