> Windows Syscalls
ntoskrnl.exeT1068T1559T1106

NtAlpcCreatePort

Creates a server-side ALPC connection port that clients can reach with NtAlpcConnectPort.

Prototype

NTSTATUS NtAlpcCreatePort(
  PHANDLE               PortHandle,
  POBJECT_ATTRIBUTES    ObjectAttributes,
  PALPC_PORT_ATTRIBUTES PortAttributes
);

Arguments

NameTypeDirDescription
PortHandlePHANDLEoutReceives the handle to the new server connection port.
ObjectAttributesPOBJECT_ATTRIBUTESinNames the port in the object namespace (e.g. \RPC Control\foo) and supplies a SECURITY_DESCRIPTOR.
PortAttributesPALPC_PORT_ATTRIBUTESinPort limits and behaviour (MaxMessageLength, MemoryBandwidth, MaxViewSize, SecurityQos, Flags).

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070x77win10-1507
Win10 16070x77win10-1607
Win10 17030x78win10-1703
Win10 17090x78win10-1709
Win10 18030x79win10-1803
Win10 18090x79win10-1809
Win10 19030x79win10-1903
Win10 19090x79win10-1909
Win10 20040x7Bwin10-2004
Win10 20H20x7Bwin10-20h2
Win10 21H10x7Bwin10-21h1
Win10 21H20x7Bwin10-21h2
Win10 22H20x7Bwin10-22h2
Win11 21H20x7Bwin11-21h2
Win11 22H20x7Bwin11-22h2
Win11 23H20x7Bwin11-23h2
Win11 24H20x7Dwin11-24h2
Server 20160x77winserver-2016
Server 20190x79winserver-2019
Server 20220x7Bwinserver-2022
Server 20250x7Dwinserver-2025

Kernel module

ntoskrnl.exeNtAlpcCreatePort

Related APIs

NtAlpcConnectPortNtAlpcAcceptConnectPortNtAlpcSendWaitReceivePortNtAlpcDisconnectPortRpcServerUseProtseqEpWRpcServerRegisterIfEx

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

Undocumented notes

`NtAlpcCreatePort` allocates the server-side **connection port** — the listening object that clients later target with `NtAlpcConnectPort`. The handle returned is *not* yet a communication endpoint; it is the bind socket. Each accepted client gets its own per-connection port via `NtAlpcAcceptConnectPort`. Server processes typically register the port under `\RPC Control\<endpoint>` (for RPC over `ncalrpc`) or `\Sessions\<n>\AppContainerNamedObjects\...` (for AppContainer-isolated IPC). The kernel implementation lives in `AlpcpCreateConnectionPort` inside ntoskrnl.exe.

Common malware usage

Three angles seen in the wild: 1. **Malicious RPC server**: an implant exposes a `\RPC Control\<name>` port for peer implants to issue commands, often combined with a captured ETW or NDIS service token to make the connection appear to come from a privileged context. 2. **CVE setup**: every ALPC LPE PoC builds the bug-triggering scaffolding around a pair of `NtAlpcCreatePort` calls — one for the rogue server, one for the spoof handshake (e.g. SandboxEscaper's *AlpcRpcGetUserName* trick before CVE-2018-8440). 3. **Stealth peer-to-peer C2**: a beacon process running as SYSTEM creates an ACL-restricted ALPC port; a second user-context implant connects to it. Traffic is entirely in-kernel and never reaches the network stack.

Detection opportunities

Enumerating ALPC ports per process (SystemInformer, `!alpc` in WinDbg, or `Get-WinEvent -ProviderName 'Microsoft-Windows-Kernel-ALPC'` if enabled) reveals non-Microsoft processes hosting a connection port — a very small population on a typical workstation. Suspicious DACLs (port allowing `Everyone` to connect, or a port owned by a user-context process named to mimic an RPC service) are strong indicators. Combine with `Microsoft-Windows-RPC` ETW to see which interfaces are registered on the port — an unregistered ALPC port that still accepts connections is by definition not RPC and warrants investigation.

Direct syscall examples

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 ENDP

cMinimal 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