NtAlpcConnectPort
Établit une connexion client ALPC vers un port serveur nommé et échange un message initial.
Prototype
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 );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| PortHandle | PHANDLE | out | Reçoit le handle vers la nouvelle connexion client ALPC. |
| PortName | PUNICODE_STRING | in | Nom du port serveur dans le namespace objet, ex. \RPC Control\foo, \Sessions\1\... . |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Attributs d'objet optionnels pour le port client ; typiquement NULL. |
| PortAttributes | PALPC_PORT_ATTRIBUTES | in | Attributs côté client du port (longueur max de message, taille de vue, QoS sécurité). |
| Flags | ULONG | in | Drapeaux ALPC_MSGFLG_* et de connexion (ex. ALPC_PORFLG_ALLOW_LPC_REQUESTS). |
| RequiredServerSid | PSID | in | SID optionnel que le noyau doit vérifier côté serveur avant d'accepter la connexion. |
| ConnectionMessage | PPORT_MESSAGE | in/out | Payload du message de connexion ; mis à jour avec la réponse d'acceptation du serveur au retour. |
| BufferLength | PULONG | in/out | En entrée, taille de ConnectionMessage ; en sortie, taille de la réponse serveur. |
| OutMessageAttributes | PALPC_MESSAGE_ATTRIBUTES | in/out | Attributs de message (handle, contexte sécurité, vue) que le client envoie dans le connect. |
| InMessageAttributes | PALPC_MESSAGE_ATTRIBUTES | in/out | Reçoit les attributs de la réponse serveur (ex. handles de vue partagée). |
| Timeout | PLARGE_INTEGER | in | Délai optionnel pour le handshake de connexion (unités de 100 ns, négatif = relatif). |
IDs de syscalls par version de Windows
| Version 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 |
Module noyau
APIs liées
Stub du 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
Notes non documentées
ALPC (Advanced/Asynchronous Local Procedure Call) est le successeur moderne et non documenté du sous-système LPC historique, et le substrat de quasiment tous les services RPC Windows n'utilisant ni SMB ni TCP. `NtAlpcConnectPort` est le handshake côté client — l'équivalent de `connect()` pour les ports ALPC. **Aucune surface Win32 publique** ; les consommateurs y accèdent indirectement via le runtime RPC (`RpcBindingFromStringBindingW` avec la séquence `ncalrpc`) ou, plus bas, via l'IPC TraceLogging d'ETW. La signature à 11 arguments est fidèlement reproduite par phnt et SystemInformer.
Usage courant par les malwares
ALPC est une surface d'élévation de privilèges, pas d'exécution de code. CVE-2018-8440 (LPE *ALPC Task Scheduler* de SandboxEscaper) a abusé d'un appel SetSecurityInfo joignable via une connexion ALPC depuis n'importe quel utilisateur pour prendre des fichiers SYSTEM. PrintNightmare (CVE-2021-1675 / 34527) et des exploits voisins de Follina atteignent aussi le Print Spooler et les services de diagnostic via ALPC. Au-delà de l'exploitation, des implants avancés utilisent parfois ALPC comme canal C2 furtif intra-process ou intra-host entre composants coopérants (loader ↔ DLL injectée ↔ service de persistance) car le trafic ALPC est invisible aux événements réseau Sysmon et à la plupart des EDR.
Opportunités de détection
Le provider ETW `Microsoft-Windows-Kernel-ALPC` expose les événements connect/send/receive par port mais est rarement actif par défaut — l'activer à grande échelle coûte cher. Les EDR qui hookent `NtAlpcConnectPort` en user mode (ou dans `kernel.appcore.dll`) peuvent corréler le nom du port avec le processus appelant : connexions depuis un processus non système vers des ports à forte valeur (`\RPC Control\AppInfo`, `\RPC Control\SECLOGON`, `\Sessions\1\Windows\BaseNamedObjects\spoolss`) méritent une alerte. Les outils forensiques comme SystemInformer énumèrent les ports ALPC par processus, méthode la plus fiable en post-incident.
Exemples de syscalls directs
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;
}Mappings MITRE ATT&CK
Last verified: 2026-05-20