> Windows Syscalls
ntoskrnl.exeT1068T1134T1559

NtAlpcOpenSenderThread

Server-side helper that opens a HANDLE to the thread that sent a given ALPC message.

Prototype

NTSTATUS NtAlpcOpenSenderThread(
  PHANDLE             ThreadHandle,
  HANDLE              PortHandle,
  PPORT_MESSAGE       PortMessage,
  ULONG               Flags,
  ACCESS_MASK         DesiredAccess,
  POBJECT_ATTRIBUTES  ObjectAttributes
);

Arguments

NameTypeDirDescription
ThreadHandlePHANDLEoutReceives a HANDLE to the sender's ETHREAD object, opened with DesiredAccess.
PortHandleHANDLEinHandle to the server's ALPC communication port that received the message.
PortMessagePPORT_MESSAGEinThe PORT_MESSAGE just returned from NtAlpcSendWaitReceivePort; its ClientId.UniqueThread identifies the sending thread.
FlagsULONGinReserved / context flags. Typically 0.
DesiredAccessACCESS_MASKinAccess mask for the returned handle (e.g. THREAD_QUERY_LIMITED_INFORMATION for identity, THREAD_GET_CONTEXT for stack inspection).
ObjectAttributesPOBJECT_ATTRIBUTESinObject-attributes block (usually inheritance flags only). May be NULL.

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070x84win10-1507
Win10 16070x84win10-1607
Win10 17030x85win10-1703
Win10 17090x85win10-1709
Win10 18030x86win10-1803
Win10 18090x86win10-1809
Win10 19030x86win10-1903
Win10 19090x86win10-1909
Win10 20040x88win10-2004
Win10 20H20x88win10-20h2
Win10 21H10x88win10-21h1
Win10 21H20x88win10-21h2
Win10 22H20x88win10-22h2
Win11 21H20x88win11-21h2
Win11 22H20x88win11-22h2
Win11 23H20x88win11-23h2
Win11 24H20x8Awin11-24h2
Server 20160x84winserver-2016
Server 20190x86winserver-2019
Server 20220x88winserver-2022
Server 20250x8Awinserver-2025

Kernel module

ntoskrnl.exeNtAlpcOpenSenderThread

Related APIs

NtAlpcOpenSenderProcessNtAlpcImpersonateClientOfPortNtAlpcSendWaitReceivePortNtOpenThreadTokenNtGetContextThreadNtQueryInformationThread

Syscall stub

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

Thread-level analogue of `NtAlpcOpenSenderProcess`. Where the process-level helper answers *who* called, the thread helper answers *which thread inside who* called — useful when a server needs to distinguish multiple concurrent requests from the same client process (typical in RPC servers that pool worker threads on the client side). The kernel implementation `AlpcpOpenSenderThread` walks the same path as the process variant but resolves the ETHREAD from `ClientId.UniqueThread`. Common access masks: `THREAD_QUERY_LIMITED_INFORMATION` (to read `ThreadDynamicCodePolicy`, attestation state), `THREAD_SUSPEND_RESUME` (rare; freezes the caller during a critical section).

Common malware usage

Used less often than the process variant, but the same forgotten-check vulnerability class applies. A specific abuse pattern: a server that wants to honour a per-thread *impersonation token* may open the sender thread, then call `NtOpenThreadToken(...TRUE /*OpenAsSelf*/)` to grab the token without going through the formal `NtAlpcImpersonateClientOfPort` path — bypassing the ALPC QoS policy. The Forshaw-Sandbox-Escape research catalogue includes at least two cases (Spooler, Search Indexer) where this token-grab via `NtAlpcOpenSenderThread` enabled a SYSTEM-token theft from a non-privileged caller. Also useful offensively for thread-context disclosure: an attacker who has compromised a privileged RPC server can call `NtAlpcOpenSenderThread` with `THREAD_GET_CONTEXT` and snapshot any connecting client's registers — a cheap memory-disclosure primitive.

Detection opportunities

Same allowlist logic as `NtAlpcOpenSenderProcess` — the legitimate callers are a small, identifiable set. Any opening of `THREAD_GET_CONTEXT` or `THREAD_SUSPEND_RESUME` on the sender is a strong outlier and worth alerting on regardless of process. ETW provider `Microsoft-Windows-Threat-Intelligence` (when enabled on Defender for Endpoint) emits thread-handle-open events with the originating syscall — this is the cleanest signal. From userspace, hooking `NtAlpcOpenSenderThread` in ntdll catches user-mode RPC servers but misses kernel callers; combine with the kernel-syscall ETW.

Direct syscall examples

cPer-thread context inspection

// Server-side: get the sending thread, then read its UMS / dynamic-code policy.
#include <windows.h>
#include <winternl.h>

NTSTATUS NTAPI NtAlpcOpenSenderThread(
    PHANDLE, HANDLE, PPORT_MESSAGE, ULONG, ACCESS_MASK, POBJECT_ATTRIBUTES);

BOOL CallerThreadAllowsDynCode(HANDLE serverPort, PPORT_MESSAGE msg) {
    HANDLE hThr = NULL;
    if (NtAlpcOpenSenderThread(
            &hThr, serverPort, msg,
            0,
            THREAD_QUERY_LIMITED_INFORMATION,
            NULL) < 0) {
        return FALSE;
    }
    PROCESS_MITIGATION_DYNAMIC_CODE_POLICY pol = {0};
    BOOL ok = GetThreadInformation(hThr, ThreadDynamicCodePolicy, &pol, sizeof(pol));
    CloseHandle(hThr);
    return ok && !pol.ProhibitDynamicCode;
}

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtAlpcOpenSenderThread (SSN 0x8A on Win11 24H2 / Server 2025)
NtAlpcOpenSenderThread PROC
    mov  r10, rcx          ; ThreadHandle
    mov  eax, 8Ah          ; SSN
    syscall
    ret
NtAlpcOpenSenderThread ENDP

MITRE ATT&CK mappings

Last verified: 2026-05-20