NtAlpcAcceptConnectPort
Acceptation ALPC côté serveur — finalise une demande de connexion client en attente et renvoie un port de communication par client.
Prototype
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 );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| PortHandle | PHANDLE | out | Reçoit un handle vers le nouveau port de communication par client (ou NULL si AcceptConnection vaut FALSE). |
| ConnectionPortHandle | HANDLE | in | Handle vers le port de connexion serveur en écoute, créé précédemment avec NtAlpcCreatePort. |
| Flags | ULONG | in | Drapeaux de connexion ALPC (ALPC_MSGFLG_SYNC_REQUEST, ALPC_PORFLG_*) ; généralement 0. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Attributs d'objet optionnels pour le nouveau port de communication ; généralement NULL. |
| PortAttributes | PALPC_PORT_ATTRIBUTES | in | Attributs côté serveur du port (taille max message, taille de vue, QoS de sécurité) régissant ce port client. |
| PortContext | PVOID | in | Valeur de contexte opaque que le serveur récupère ensuite à chaque réception sur ce port — typiquement un pointeur vers une struct par client. |
| ConnectionRequest | PPORT_MESSAGE | in | Le PORT_MESSAGE LPC_CONNECTION_REQUEST original reçu via NtAlpcSendWaitReceivePort qui a déclenché cette acceptation. |
| ConnectionMessageAttributes | PALPC_MESSAGE_ATTRIBUTES | in | Attributs de message (handle, contexte sécurité, vue) renvoyés au client comme payload de la réponse d'acceptation. |
| AcceptConnection | BOOLEAN | in | TRUE pour accepter la connexion (renvoie un handle de port) ; FALSE pour la refuser (le client reçoit STATUS_PORT_CONNECTION_REFUSED). |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | 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 |
Module noyau
APIs liées
Stub du syscall
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
Notes non documentées
`NtAlpcAcceptConnectPort` est le pendant exact de `NtAlpcConnectPort` : le côté serveur du handshake à trois temps ALPC. Le pattern canonique est `NtAlpcCreatePort` (bind/listen) → `NtAlpcSendWaitReceivePort` (recv `LPC_CONNECTION_REQUEST`) → `NtAlpcAcceptConnectPort` (accept ou reject). Un accept réussi renvoie un port de communication par client ; le trafic de messages ultérieur passe par ce handle, pas par le port de connexion. Tout service RPC Windows exposant un endpoint `ncalrpc` exécute cette boucle, presque toujours via le wrapper `RPCRT4!RpcServerListen` plutôt qu'en appelant la routine Nt directement. Aucune surface Win32 publique.
Usage courant par les malwares
En soi, appeler `NtAlpcAcceptConnectPort` depuis un malware est inhabituel — cela implique que le malware héberge *lui-même* un endpoint serveur ALPC pour coordonner d'autres composants (loader ↔ DLL injectée ↔ service de persistance). Certains implants modulaires longue durée font exactement cela, ALPC étant invisible à la télémétrie réseau Sysmon et survivant même sans réseau sortant. Plus souvent, le syscall est intéressant en sens *inverse* : les chaînes d'exploits ALPC LPE (CVE-2018-8440 Task Scheduler, multiples bugs Print Spooler) finissent par tromper la boucle d'accept d'un serveur *privilégié* via un `PORT_MESSAGE` LPC_CONNECTION_REQUEST forgé — le bug est dans l'appelant de `NtAlpcAcceptConnectPort`, pas dans le syscall.
Opportunités de détection
Détection asymétrique : ce syscall est dominé par chaque service légitime de la machine. Le signal réside dans *quel* processus l'appelle. Lancer `handle.exe -a -p <pid>` (ou équivalent) sur un binaire non service / non Microsoft et y trouver un endpoint serveur `ALPC Port \RPC Control\…` est anormal. ETW `Microsoft-Windows-Kernel-ALPC` expose des événements d'accept par port mais est rarement actif à grande échelle. L'onglet ALPC de SystemInformer énumère les ports serveur par processus — outil le plus utile en post-incident.
Exemples de syscalls directs
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;
}Mappings MITRE ATT&CK
Last verified: 2026-05-20