NtAlpcOpenSenderThread
Server-seitiger Helper, der ein HANDLE auf den Thread öffnet, der eine bestimmte ALPC-Nachricht gesendet hat.
Prototyp
NTSTATUS NtAlpcOpenSenderThread( PHANDLE ThreadHandle, HANDLE PortHandle, PPORT_MESSAGE PortMessage, ULONG Flags, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ThreadHandle | PHANDLE | out | Empfängt ein HANDLE auf das ETHREAD-Objekt des Senders, geöffnet mit DesiredAccess. |
| PortHandle | HANDLE | in | Handle auf den ALPC-Kommunikationsport des Servers, der die Nachricht empfangen hat. |
| PortMessage | PPORT_MESSAGE | in | Die gerade von NtAlpcSendWaitReceivePort gelieferte PORT_MESSAGE; ihre ClientId.UniqueThread identifiziert den sendenden Thread. |
| Flags | ULONG | in | Reservierte / Kontext-Flags. Üblicherweise 0. |
| DesiredAccess | ACCESS_MASK | in | Access-Mask für das zurückgegebene Handle (z. B. THREAD_QUERY_LIMITED_INFORMATION für Identität, THREAD_GET_CONTEXT für Stack-Inspektion). |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Object-Attributes-Block (üblicherweise nur Vererbungs-Flags). Kann NULL sein. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x84 | win10-1507 |
| Win10 1607 | 0x84 | win10-1607 |
| Win10 1703 | 0x85 | win10-1703 |
| Win10 1709 | 0x85 | win10-1709 |
| Win10 1803 | 0x86 | win10-1803 |
| Win10 1809 | 0x86 | win10-1809 |
| Win10 1903 | 0x86 | win10-1903 |
| Win10 1909 | 0x86 | win10-1909 |
| Win10 2004 | 0x88 | win10-2004 |
| Win10 20H2 | 0x88 | win10-20h2 |
| Win10 21H1 | 0x88 | win10-21h1 |
| Win10 21H2 | 0x88 | win10-21h2 |
| Win10 22H2 | 0x88 | win10-22h2 |
| Win11 21H2 | 0x88 | win11-21h2 |
| Win11 22H2 | 0x88 | win11-22h2 |
| Win11 23H2 | 0x88 | win11-23h2 |
| Win11 24H2 | 0x8A | win11-24h2 |
| Server 2016 | 0x84 | winserver-2016 |
| Server 2019 | 0x86 | winserver-2019 |
| Server 2022 | 0x88 | winserver-2022 |
| Server 2025 | 0x8A | winserver-2025 |
Kernel-Modul
Verwandte APIs
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
Undokumentierte Hinweise
Thread-Level-Analogon zu `NtAlpcOpenSenderProcess`. Wo der Prozess-Helper *wer* gerufen hat beantwortet, beantwortet der Thread-Helper *welcher Thread innerhalb wem* gerufen hat — nützlich, wenn ein Server mehrere konkurrierende Requests vom gleichen Client-Prozess unterscheiden muss (typisch in RPC-Servern, die client-seitig Worker-Threads poolen). Die Kernel-Implementierung `AlpcpOpenSenderThread` läuft denselben Pfad wie die Prozess-Variante, löst aber das ETHREAD aus `ClientId.UniqueThread` auf. Übliche Access-Masks: `THREAD_QUERY_LIMITED_INFORMATION` (zum Lesen von `ThreadDynamicCodePolicy`, Attestation-State), `THREAD_SUSPEND_RESUME` (selten; friert den Caller während einer Critical Section ein).
Häufige Malware-Nutzung
Weniger genutzt als die Prozess-Variante, aber dieselbe Vulnerability-Klasse (vergessener Check) gilt. Ein spezifisches Missbrauchs-Muster: ein Server, der einen per-Thread-*Impersonation-Token* ehren will, kann den Sender-Thread öffnen und dann `NtOpenThreadToken(...TRUE /*OpenAsSelf*/)` rufen, um das Token zu greifen ohne den formalen `NtAlpcImpersonateClientOfPort`-Pfad — die ALPC-QoS-Policy umgehend. Forshaws Sandbox-Escape-Forschungskatalog enthält mindestens zwei Fälle (Spooler, Search Indexer), wo dieser Token-Grab via `NtAlpcOpenSenderThread` einen SYSTEM-Token-Diebstahl aus einem unprivilegierten Caller ermöglichte. Offensiv auch für Thread-Context-Disclosure nützlich: ein Angreifer, der einen privilegierten RPC-Server kompromittiert hat, kann `NtAlpcOpenSenderThread` mit `THREAD_GET_CONTEXT` rufen und die Register jedes verbindenden Clients snapshotten — eine billige Memory-Disclosure-Primitive.
Erkennungsmöglichkeiten
Gleiche Allowlist-Logik wie `NtAlpcOpenSenderProcess` — die legitimen Aufrufer sind eine kleine, identifizierbare Menge. Jedes Öffnen mit `THREAD_GET_CONTEXT` oder `THREAD_SUSPEND_RESUME` auf dem Sender ist ein starker Outlier und alertierungswürdig — unabhängig vom Prozess. Der ETW-Provider `Microsoft-Windows-Threat-Intelligence` (wenn auf Defender for Endpoint aktiviert) emittiert Thread-Handle-Open-Events mit Ursprungs-Syscall — das sauberste Signal. Aus dem Userspace fängt das Hooken von `NtAlpcOpenSenderThread` in ntdll User-Mode-RPC-Server, verfehlt aber Kernel-Aufrufer; mit Kernel-Syscall-ETW kombinieren.
Direkte Syscall-Beispiele
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 ENDPMITRE ATT&CK-Mappings
Last verified: 2026-05-20