NtAlpcCreatePort
Erzeugt einen serverseitigen ALPC-Connection-Port, den Clients per NtAlpcConnectPort erreichen können.
Prototyp
NTSTATUS NtAlpcCreatePort( PHANDLE PortHandle, POBJECT_ATTRIBUTES ObjectAttributes, PALPC_PORT_ATTRIBUTES PortAttributes );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| PortHandle | PHANDLE | out | Empfängt das Handle des neuen Server-Connection-Ports. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Benennt den Port im Object-Namespace (z. B. \RPC Control\foo) und liefert einen SECURITY_DESCRIPTOR. |
| PortAttributes | PALPC_PORT_ATTRIBUTES | in | Port-Limits und -Verhalten (MaxMessageLength, MemoryBandwidth, MaxViewSize, SecurityQos, Flags). |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x77 | win10-1507 |
| Win10 1607 | 0x77 | win10-1607 |
| Win10 1703 | 0x78 | win10-1703 |
| Win10 1709 | 0x78 | win10-1709 |
| Win10 1803 | 0x79 | win10-1803 |
| Win10 1809 | 0x79 | win10-1809 |
| Win10 1903 | 0x79 | win10-1903 |
| Win10 1909 | 0x79 | win10-1909 |
| Win10 2004 | 0x7B | win10-2004 |
| Win10 20H2 | 0x7B | win10-20h2 |
| Win10 21H1 | 0x7B | win10-21h1 |
| Win10 21H2 | 0x7B | win10-21h2 |
| Win10 22H2 | 0x7B | win10-22h2 |
| Win11 21H2 | 0x7B | win11-21h2 |
| Win11 22H2 | 0x7B | win11-22h2 |
| Win11 23H2 | 0x7B | win11-23h2 |
| Win11 24H2 | 0x7D | win11-24h2 |
| Server 2016 | 0x77 | winserver-2016 |
| Server 2019 | 0x79 | winserver-2019 |
| Server 2022 | 0x7B | winserver-2022 |
| Server 2025 | 0x7D | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 7D 00 00 00 mov eax, 0x7D 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
`NtAlpcCreatePort` allokiert den **Connection-Port** auf Server-Seite — das Lausch-Objekt, das Clients später per `NtAlpcConnectPort` adressieren. Das zurückgegebene Handle ist *noch kein* Communication-Endpoint; es ist die Bind-Socket. Jeder akzeptierte Client bekommt einen eigenen Per-Connection-Port über `NtAlpcAcceptConnectPort`. Serverprozesse registrieren den Port typischerweise unter `\RPC Control\<Endpoint>` (für RPC über `ncalrpc`) oder `\Sessions\<n>\AppContainerNamedObjects\...` (für AppContainer-isolierten IPC). Die Kernel-Implementierung lebt in `AlpcpCreateConnectionPort` in ntoskrnl.exe.
Häufige Malware-Nutzung
Drei in der Wildnis beobachtete Winkel: 1. **Schädlicher RPC-Server**: ein Implant exponiert einen `\RPC Control\<Name>`-Port, damit Peer-Implants Befehle absetzen — oft kombiniert mit einem gestohlenen ETW- oder NDIS-Service-Token, damit die Verbindung aus privilegiertem Kontext zu kommen scheint. 2. **Exploit-Setup**: jeder ALPC-LPE-PoC baut die Trigger-Infrastruktur um ein Paar `NtAlpcCreatePort`-Aufrufe — einer für den Fake-Server, einer für den nachgemachten Handshake (z. B. SandboxEscapers *AlpcRpcGetUserName*-Trick vor CVE-2018-8440). 3. **Verdeckter Peer-to-Peer-C2**: ein Beacon, der als SYSTEM läuft, erzeugt einen ACL-eingeschränkten ALPC-Port; ein zweites Implant im User-Context verbindet sich. Verkehr bleibt komplett im Kernel und erreicht den Netzwerk-Stack nie.
Erkennungsmöglichkeiten
ALPC-Ports pro Prozess enumerieren (SystemInformer, `!alpc` in WinDbg, oder `Get-WinEvent -ProviderName 'Microsoft-Windows-Kernel-ALPC'` falls aktiv) zeigt Nicht-Microsoft-Prozesse, die einen Connection-Port hosten — eine sehr kleine Population auf einer typischen Workstation. Verdächtige DACLs (Port, der `Everyone` Verbindung erlaubt, oder Port im Besitz eines User-Context-Prozesses mit RPC-Service-Imitations-Namen) sind starke Indikatoren. Mit ETW `Microsoft-Windows-RPC` kombinieren, um zu sehen, welche Interfaces auf dem Port registriert sind — ein ALPC-Port ohne registriertes Interface, der Verbindungen akzeptiert, ist per Definition kein RPC und gehört untersucht.
Direkte Syscall-Beispiele
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtAlpcCreatePort (SSN 0x7D on Win11 24H2)
NtAlpcCreatePort PROC
mov r10, rcx ; PortHandle
mov eax, 7Dh ; SSN — version-sensitive, resolve dynamically
syscall
ret
NtAlpcCreatePort ENDPcMinimal LRPC server bind
// Create \RPC Control\demo_port as a server connection port.
#include <windows.h>
#include <winternl.h>
typedef struct _ALPC_PORT_ATTRIBUTES {
ULONG Flags;
SECURITY_QUALITY_OF_SERVICE SecurityQos;
SIZE_T MaxMessageLength;
SIZE_T MemoryBandwidth;
SIZE_T MaxPoolUsage;
SIZE_T MaxSectionSize;
SIZE_T MaxViewSize;
SIZE_T MaxTotalSectionSize;
ULONG DupObjectTypes;
#ifdef _WIN64
ULONG Reserved;
#endif
} ALPC_PORT_ATTRIBUTES, *PALPC_PORT_ATTRIBUTES;
typedef NTSTATUS (NTAPI *pNtAlpcCreatePort)(
PHANDLE, POBJECT_ATTRIBUTES, PALPC_PORT_ATTRIBUTES);
HANDLE CreateServer(LPCWSTR name) {
UNICODE_STRING us; RtlInitUnicodeString(&us, name);
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &us, OBJ_CASE_INSENSITIVE, NULL, NULL);
ALPC_PORT_ATTRIBUTES pa = {0};
pa.MaxMessageLength = 0x1000;
pa.SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
pa.SecurityQos.ImpersonationLevel = SecurityImpersonation;
pa.SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
pa.SecurityQos.EffectiveOnly = FALSE;
HANDLE hPort = NULL;
pNtAlpcCreatePort fn = (pNtAlpcCreatePort)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtAlpcCreatePort");
fn(&hPort, &oa, &pa);
return hPort;
}rustwindows-sys handle wrapper
// Cargo: windows-sys = "0.59", features = ["Wdk_Foundation", "Win32_Foundation"]
use std::ptr::null_mut;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Wdk::Foundation::OBJECT_ATTRIBUTES;
// Phnt ALPC bindings are not in windows-sys today; resolve dynamically.
type FnCreate = unsafe extern "system" fn(
*mut HANDLE, *const OBJECT_ATTRIBUTES, *const u8,
) -> i32;
pub unsafe fn create_alpc_port(
name_obj_attrs: *const OBJECT_ATTRIBUTES,
attrs: *const u8,
) -> HANDLE {
let ntdll = libloading::Library::new("ntdll.dll").unwrap();
let f: libloading::Symbol<FnCreate> = ntdll.get(b"NtAlpcCreatePort\0").unwrap();
let mut h: HANDLE = 0;
let _ = f(&mut h, name_obj_attrs, attrs);
h
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20