> Windows Syscalls
ntoskrnl.exeT1055T1106

NtCancelWaitCompletionPacket

Cancels a previously associated wait-completion packet, removing the dispatcher-object binding.

Prototype

NTSTATUS NtCancelWaitCompletionPacket(
  HANDLE  WaitCompletionPacketHandle,
  BOOLEAN RemoveSignaledPacket
);

Arguments

NameTypeDirDescription
WaitCompletionPacketHandleHANDLEinHandle to a wait-completion packet obtained from NtCreateWaitCompletionPacket.
RemoveSignaledPacketBOOLEANinIf TRUE and the packet already fired, also dequeue the resulting completion entry from the IOCP.

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070x90win10-1507
Win10 16070x90win10-1607
Win10 17030x91win10-1703
Win10 17090x92win10-1709
Win10 18030x93win10-1803
Win10 18090x93win10-1809
Win10 19030x93win10-1903
Win10 19090x93win10-1909
Win10 20040x95win10-2004
Win10 20H20x95win10-20h2
Win10 21H10x95win10-21h1
Win10 21H20x95win10-21h2
Win10 22H20x95win10-22h2
Win11 21H20x95win11-21h2
Win11 22H20x95win11-22h2
Win11 23H20x95win11-23h2
Win11 24H20x97win11-24h2
Server 20160x90winserver-2016
Server 20190x93winserver-2019
Server 20220x95winserver-2022
Server 20250x97winserver-2025

Kernel module

ntoskrnl.exeNtCancelWaitCompletionPacket

Related APIs

NtAssociateWaitCompletionPacketNtCreateWaitCompletionPacketTpSetWaitTpWaitForWaitCreateThreadpoolWaitSetThreadpoolWait

Syscall stub

4C 8B D1            mov r10, rcx
B8 97 00 00 00      mov eax, 0x97      ; Win11 24H2 SSN
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

Undocumented notes

Pairs with `NtAssociateWaitCompletionPacket`. The threadpool wait subsystem internally creates a `WAIT_COMPLETION_PACKET` (a kernel object that binds together a dispatcher object — event, semaphore, mutant, timer — and an IOCP into which a completion entry will be posted when the dispatcher signals). `NtCancelWaitCompletionPacket` unbinds the packet so it can be reassociated with a different dispatcher (the typical reason ntdll calls it: a `TpSetWait` reuses an existing packet on the threadpool's wait object). The `RemoveSignaledPacket` flag handles the race where the packet fired between the caller's last completion-poll and the cancellation — TRUE eats the orphan completion entry so it doesn't pop out of `GetQueuedCompletionStatus` unexpectedly.

Common malware usage

Almost always paired with `NtAssociateWaitCompletionPacket` in offensive use. In **PoolParty's "Worker Factory via Wait Completion" variant** the cleanup step uses `NtCancelWaitCompletionPacket` to detach the forged packet after the threadpool worker has been induced to dispatch into shellcode — leaving the wait infrastructure cleanly reset so the target process doesn't crash on the next legitimate `TpSetWait`. Standalone use is rare offensively: cancellation alone confers no capability. It does, however, sometimes appear as a forensic artifact in memory captures of injected processes — an `EPROCESS` whose handle table contains a `WaitCompletionPacket` object the process never created itself is a strong indicator that injection occurred.

Detection opportunities

Low standalone signal — ntdll's `TpWaitForWait`/`TpSetWait` paths emit these calls constantly in any non-trivial program. The detection value lies in *cross-process* patterns: a handle of type `WaitCompletionPacket` showing up in another process's handle table (Sysmon Event 10 / kernel handle table dumps via `!handle` in WinDbg) is anomalous because these objects are normally process-local. EDRs that watch threadpool data structures (`_TP_TIMER`, `_TP_WAIT`) for foreign callback addresses will surface the broader PoolParty pattern.

Direct syscall examples

cCancel + reassociate (ntdll-style reuse)

// Reuse an existing wait packet on a different event.
NtCancelWaitCompletionPacket(hPacket, TRUE /* eat orphan completion */);
NtAssociateWaitCompletionPacket(
    hPacket,
    hIoCompletion,
    hNewEvent,                      // new dispatcher
    (PVOID)keyContext, (PVOID)apc,
    STATUS_SUCCESS, 0, NULL);

asmx64 direct stub

; NtCancelWaitCompletionPacket direct syscall (Win11 24H2 SSN 0x97)
NtCancelWaitCompletionPacket PROC
    mov  r10, rcx
    mov  eax, 97h
    syscall
    ret
NtCancelWaitCompletionPacket ENDP

MITRE ATT&CK mappings

Last verified: 2026-05-20