NtAlpcAcceptConnectPort
Server-seitige ALPC-Accept-Routine — schließt eine ausstehende Client-Verbindung ab und liefert einen Per-Client-Kommunikationsport.
Prototyp
NTSTATUS NtAlpcAcceptConnectPort( PHANDLE PortHandle, HANDLE ConnectionPortHandle, ULONG Flags, POBJECT_ATTRIBUTES ObjectAttributes, PALPC_PORT_ATTRIBUTES PortAttributes, PVOID PortContext, PPORT_MESSAGE ConnectionRequest, PALPC_MESSAGE_ATTRIBUTES ConnectionMessageAttributes, BOOLEAN AcceptConnection );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| PortHandle | PHANDLE | out | Empfängt ein Handle auf den neuen Per-Client-Kommunikationsport (oder NULL, wenn AcceptConnection FALSE ist). |
| ConnectionPortHandle | HANDLE | in | Handle auf den lauschenden Server-Connection-Port, zuvor mit NtAlpcCreatePort erstellt. |
| Flags | ULONG | in | ALPC-Verbindungsflags (ALPC_MSGFLG_SYNC_REQUEST, ALPC_PORFLG_*); meist 0. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Optionale Objektattribute für den neuen Kommunikationsport; meist NULL. |
| PortAttributes | PALPC_PORT_ATTRIBUTES | in | Server-seitige Port-Attribute (Max-Message-Größe, View-Größe, Security-QoS) für diesen Client-Port. |
| PortContext | PVOID | in | Opaker Kontextwert, den der Server bei jedem Empfang auf diesem Port wieder erhält — meist ein Zeiger auf eine Per-Client-Struktur. |
| ConnectionRequest | PPORT_MESSAGE | in | Die ursprüngliche LPC_CONNECTION_REQUEST-PORT_MESSAGE, empfangen über NtAlpcSendWaitReceivePort, die dieses Accept ausgelöst hat. |
| ConnectionMessageAttributes | PALPC_MESSAGE_ATTRIBUTES | in | Message-Attribute (Handle, Security-Context, View), die als Accept-Reply-Payload an den Client zurückgehen. |
| AcceptConnection | BOOLEAN | in | TRUE, um die Verbindung anzunehmen (liefert ein Port-Handle); FALSE, um sie abzulehnen (Client erhält STATUS_PORT_CONNECTION_REFUSED). |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x73 | win10-1507 |
| Win10 1607 | 0x73 | win10-1607 |
| Win10 1703 | 0x74 | win10-1703 |
| Win10 1709 | 0x74 | win10-1709 |
| Win10 1803 | 0x75 | win10-1803 |
| Win10 1809 | 0x75 | win10-1809 |
| Win10 1903 | 0x75 | win10-1903 |
| Win10 1909 | 0x75 | win10-1909 |
| Win10 2004 | 0x77 | win10-2004 |
| Win10 20H2 | 0x77 | win10-20h2 |
| Win10 21H1 | 0x77 | win10-21h1 |
| Win10 21H2 | 0x77 | win10-21h2 |
| Win10 22H2 | 0x77 | win10-22h2 |
| Win11 21H2 | 0x77 | win11-21h2 |
| Win11 22H2 | 0x77 | win11-22h2 |
| Win11 23H2 | 0x77 | win11-23h2 |
| Win11 24H2 | 0x79 | win11-24h2 |
| Server 2016 | 0x73 | winserver-2016 |
| Server 2019 | 0x75 | winserver-2019 |
| Server 2022 | 0x77 | winserver-2022 |
| Server 2025 | 0x79 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 79 00 00 00 mov eax, 0x79 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
`NtAlpcAcceptConnectPort` ist das exakte Gegenstück zu `NtAlpcConnectPort`: die Server-Seite des ALPC-Drei-Wege-Handshakes. Das kanonische Muster: `NtAlpcCreatePort` (bind/listen) → `NtAlpcSendWaitReceivePort` (Empfang `LPC_CONNECTION_REQUEST`) → `NtAlpcAcceptConnectPort` (accept oder reject). Ein erfolgreiches Accept liefert einen Per-Client-Kommunikationsport; nachfolgender Nachrichtenverkehr fließt über dieses Handle, nicht über den Connection-Port. Jeder Windows-RPC-Dienst, der einen `ncalrpc`-Endpoint exponiert, fährt diese Schleife, fast immer via Wrapper `RPCRT4!RpcServerListen` und nicht direkt über die Nt-Routine. Es gibt keine öffentliche Win32-Oberfläche.
Häufige Malware-Nutzung
Für sich allein ist ein Aufruf von `NtAlpcAcceptConnectPort` aus Malware ungewöhnlich — er bedeutet, dass die Malware *selbst* einen ALPC-Server-Endpoint hostet, um andere Komponenten zu koordinieren (Loader ↔ injizierte DLL ↔ Persistenz-Dienst). Manche langlebigen modularen Implants tun genau das, weil ALPC für Sysmon-Netz-Telemetrie unsichtbar ist und auch ohne ausgehendes Netz funktioniert. Häufiger ist der Syscall in der *Gegenrichtung* interessant: ALPC-LPE-Exploit-Ketten (CVE-2018-8440 Task Scheduler, diverse Print-Spooler-Bugs) bringen die Accept-Schleife eines *privilegierten* Servers dazu, eine gefälschte `LPC_CONNECTION_REQUEST`-`PORT_MESSAGE` falsch zu behandeln — der Bug steckt im Aufrufer von `NtAlpcAcceptConnectPort`, nicht im Syscall.
Erkennungsmöglichkeiten
Asymmetrische Erkennung: dominiert von jedem legitimen Dienst auf der Maschine. Das Signal liegt darin, *welcher* Prozess aufruft. `handle.exe -a -p <pid>` (oder Äquivalent) auf einem Nicht-Service-/Nicht-Microsoft-Binary mit einem `ALPC Port \RPC Control\…`-Server-Endpoint ist anomal. Der ETW-Provider `Microsoft-Windows-Kernel-ALPC` liefert per-Port-Accept-Events, ist aber selten flächendeckend aktiv. SystemInformers ALPC-Tab enumeriert Server-Ports pro Prozess und ist das nützlichste Post-Incident-Werkzeug.
Direkte Syscall-Beispiele
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtAlpcAcceptConnectPort (SSN 0x79 on Win11 24H2)
NtAlpcAcceptConnectPort PROC
mov r10, rcx ; PortHandle
mov eax, 79h ; SSN — drifts per build
syscall
ret
NtAlpcAcceptConnectPort ENDPcMinimal ALPC server accept loop
// Skeleton of the canonical create → recv-connreq → accept loop.
#include <windows.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI *pNtAlpcAcceptConnectPort)(
PHANDLE, HANDLE, ULONG, POBJECT_ATTRIBUTES, PVOID,
PVOID, PPORT_MESSAGE, PVOID, BOOLEAN);
static pNtAlpcAcceptConnectPort g_accept;
NTSTATUS HandleConnReq(HANDLE hConnectionPort,
PPORT_MESSAGE pConnReq) {
HANDLE hClient = NULL;
// Per-client context — survives across receives.
PVOID ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 64);
NTSTATUS st = g_accept(&hClient, hConnectionPort, 0,
NULL, NULL, ctx, pConnReq, NULL,
TRUE /* accept */);
// hClient is now the per-client comm port — pump it with
// NtAlpcSendWaitReceivePort in a worker thread.
return st;
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20