NtAlpcConnectPort
Establece una conexión cliente ALPC con un puerto servidor con nombre e intercambia un mensaje inicial.
Prototipo
NTSTATUS NtAlpcConnectPort( PHANDLE PortHandle, PUNICODE_STRING PortName, POBJECT_ATTRIBUTES ObjectAttributes, PALPC_PORT_ATTRIBUTES PortAttributes, ULONG Flags, PSID RequiredServerSid, PPORT_MESSAGE ConnectionMessage, PULONG BufferLength, PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes, PALPC_MESSAGE_ATTRIBUTES InMessageAttributes, PLARGE_INTEGER Timeout );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| PortHandle | PHANDLE | out | Recibe el handle de la nueva conexión cliente ALPC. |
| PortName | PUNICODE_STRING | in | Nombre del puerto servidor en el espacio de objetos, p. ej. \RPC Control\foo, \Sessions\1\... . |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Atributos de objeto opcionales para el puerto cliente; típicamente NULL. |
| PortAttributes | PALPC_PORT_ATTRIBUTES | in | Atributos del puerto en el cliente (longitud máxima de mensaje, tamaño de vista, QoS de seguridad). |
| Flags | ULONG | in | Banderas ALPC_MSGFLG_* y de conexión (p. ej. ALPC_PORFLG_ALLOW_LPC_REQUESTS). |
| RequiredServerSid | PSID | in | SID opcional que el kernel debe verificar en el servidor antes de aceptar la conexión. |
| ConnectionMessage | PPORT_MESSAGE | in/out | Carga útil del mensaje de conexión; actualizada con la respuesta de aceptación del servidor. |
| BufferLength | PULONG | in/out | En entrada, tamaño de ConnectionMessage; en salida, tamaño de la respuesta del servidor. |
| OutMessageAttributes | PALPC_MESSAGE_ATTRIBUTES | in/out | Atributos del mensaje (handle, contexto de seguridad, vista) que el cliente envía en el connect. |
| InMessageAttributes | PALPC_MESSAGE_ATTRIBUTES | in/out | Recibe los atributos de la respuesta del servidor (p. ej. handles de vista compartida). |
| Timeout | PLARGE_INTEGER | in | Tiempo de espera opcional para el handshake de conexión (unidades de 100 ns, negativo = relativo). |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x75 | win10-1507 |
| Win10 1607 | 0x75 | win10-1607 |
| Win10 1703 | 0x76 | win10-1703 |
| Win10 1709 | 0x76 | win10-1709 |
| Win10 1803 | 0x77 | win10-1803 |
| Win10 1809 | 0x77 | win10-1809 |
| Win10 1903 | 0x77 | win10-1903 |
| Win10 1909 | 0x77 | win10-1909 |
| Win10 2004 | 0x79 | win10-2004 |
| Win10 20H2 | 0x79 | win10-20h2 |
| Win10 21H1 | 0x79 | win10-21h1 |
| Win10 21H2 | 0x79 | win10-21h2 |
| Win10 22H2 | 0x79 | win10-22h2 |
| Win11 21H2 | 0x79 | win11-21h2 |
| Win11 22H2 | 0x79 | win11-22h2 |
| Win11 23H2 | 0x79 | win11-23h2 |
| Win11 24H2 | 0x7B | win11-24h2 |
| Server 2016 | 0x75 | winserver-2016 |
| Server 2019 | 0x77 | winserver-2019 |
| Server 2022 | 0x79 | winserver-2022 |
| Server 2025 | 0x7B | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 7B 00 00 00 mov eax, 0x7B 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
Notas no documentadas
ALPC (Advanced/Asynchronous Local Procedure Call) es el sucesor moderno y no documentado del subsistema LPC heredado y el sustrato de casi todos los servicios RPC de Windows que no usan SMB ni TCP. `NtAlpcConnectPort` es el handshake del lado cliente — el equivalente a `connect()` para puertos ALPC. **No hay superficie Win32 pública**; los consumidores llegan a él indirectamente vía el runtime RPC (`RpcBindingFromStringBindingW` con secuencia `ncalrpc`) o, más abajo, vía el IPC TraceLogging de ETW. La firma de 11 argumentos la reproducen fielmente phnt y SystemInformer.
Uso común por malware
ALPC es superficie de elevación de privilegios, no de ejecución de código. CVE-2018-8440 (LPE *ALPC Task Scheduler* de SandboxEscaper) abusó de una llamada SetSecurityInfo alcanzable por conexión ALPC desde cualquier usuario para tomar archivos de SYSTEM. PrintNightmare (CVE-2021-1675 / 34527) y exploits cercanos a Follina también alcanzan Print Spooler y servicios de diagnóstico vía ALPC. Más allá del exploit, algunos implantes avanzados usan ALPC como canal C2 sigiloso intra-proceso o intra-host entre componentes cooperantes (loader ↔ DLL inyectada ↔ servicio de persistencia) porque el tráfico ALPC es invisible a los eventos de red de Sysmon y a la mayoría de EDRs.
Oportunidades de detección
El proveedor ETW `Microsoft-Windows-Kernel-ALPC` expone eventos connect/send/receive por puerto pero rara vez está activo por defecto — habilitarlo a escala es caro. EDRs que hookean `NtAlpcConnectPort` en user mode (o en `kernel.appcore.dll`) pueden correlacionar el nombre del puerto con el proceso llamante: conexiones desde un proceso no sistema hacia puertos de alto valor (`\RPC Control\AppInfo`, `\RPC Control\SECLOGON`, `\Sessions\1\Windows\BaseNamedObjects\spoolss`) merecen alerta. Herramientas forenses como SystemInformer enumeran puertos ALPC por proceso, método más fiable en post-incidente.
Ejemplos de syscalls directos
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtAlpcConnectPort (SSN 0x7B on Win11 24H2)
NtAlpcConnectPort PROC
mov r10, rcx ; PortHandle
mov eax, 7Bh ; SSN — drifts per build
syscall
ret
NtAlpcConnectPort ENDPcConnect to an LRPC server port
// Connect from a user-mode client to a named ALPC server port.
#include <windows.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI *pNtAlpcConnectPort)(
PHANDLE, PUNICODE_STRING, POBJECT_ATTRIBUTES, PVOID,
ULONG, PSID, PVOID, PULONG, PVOID, PVOID, PLARGE_INTEGER);
HANDLE OpenServerPort(LPCWSTR name) {
UNICODE_STRING us; RtlInitUnicodeString(&us, name);
HANDLE hPort = NULL;
ULONG bufLen = 0;
pNtAlpcConnectPort fn = (pNtAlpcConnectPort)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtAlpcConnectPort");
fn(&hPort, &us, NULL, NULL, 0, NULL, NULL, &bufLen, NULL, NULL, NULL);
return hPort;
}cRPC ncalrpc binding (high-level equivalent)
// What 99% of legitimate callers actually do — RpcBindingFromStringBindingW
// drives NtAlpcConnectPort under the hood for the ncalrpc transport.
#include <windows.h>
#include <rpc.h>
RPC_BINDING_HANDLE BindLrpc(LPCWSTR ep) {
LPWSTR bindStr = NULL;
RpcStringBindingComposeW(NULL, (RPC_WSTR)L"ncalrpc", NULL,
(RPC_WSTR)ep, NULL, (RPC_WSTR*)&bindStr);
RPC_BINDING_HANDLE h = NULL;
RpcBindingFromStringBindingW((RPC_WSTR)bindStr, &h);
RpcStringFreeW((RPC_WSTR*)&bindStr);
return h;
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20