> Windows Syscalls
ntoskrnl.exeT1571T1090T1559

NtCreateNamedPipeFile

Crée l'extrémité serveur d'un canal nommé dans l'espace de noms \Device\NamedPipe.

Prototype

NTSTATUS NtCreateNamedPipeFile(
  PHANDLE            FileHandle,
  ULONG              DesiredAccess,
  POBJECT_ATTRIBUTES ObjectAttributes,
  PIO_STATUS_BLOCK   IoStatusBlock,
  ULONG              ShareAccess,
  ULONG              CreateDisposition,
  ULONG              CreateOptions,
  ULONG              NamedPipeType,
  ULONG              ReadMode,
  ULONG              CompletionMode,
  ULONG              MaximumInstances,
  ULONG              InboundQuota,
  ULONG              OutboundQuota,
  PLARGE_INTEGER     DefaultTimeout
);

Arguments

NameTypeDirDescription
FileHandlePHANDLEoutReçoit le handle vers l'extrémité serveur nouvellement créée du canal nommé.
DesiredAccessULONGinMasque d'accès, typiquement GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE.
ObjectAttributesPOBJECT_ATTRIBUTESinNomme le canal sous \Device\NamedPipe (ex. \??\pipe\msagent_xx) et fournit le SECURITY_DESCRIPTOR.
IoStatusBlockPIO_STATUS_BLOCKoutReçoit le NTSTATUS final et le code d'information (FILE_CREATED / FILE_OPENED).
ShareAccessULONGinDrapeaux FILE_SHARE_* contrôlant la sémantique d'ouverture concurrente du canal.
CreateDispositionULONGinFILE_CREATE, FILE_OPEN ou FILE_OPEN_IF ; comportement si le nom existe déjà.
CreateOptionsULONGinFILE_SYNCHRONOUS_IO_NONALERT et apparentés — même jeu de drapeaux que NtCreateFile.
NamedPipeTypeULONGinFILE_PIPE_BYTE_STREAM_TYPE ou FILE_PIPE_MESSAGE_TYPE — format de transport.
ReadModeULONGinFILE_PIPE_BYTE_STREAM_MODE ou FILE_PIPE_MESSAGE_MODE pour les lectures.
CompletionModeULONGinFILE_PIPE_QUEUE_OPERATION (bloquant) ou FILE_PIPE_COMPLETE_OPERATION (retour immédiat).
MaximumInstancesULONGinNombre maximum d'instances serveur concurrentes pour ce nom ; PIPE_UNLIMITED_INSTANCES = 0xFF.
InboundQuotaULONGinTaille du buffer client→serveur, en octets.
OutboundQuotaULONGinTaille du buffer serveur→client, en octets.
DefaultTimeoutPLARGE_INTEGERinDélai par défaut des opérations bloquantes (unités de 100 ns, négatif = relatif). NULL = 50 ms.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070xA8win10-1507
Win10 16070xAAwin10-1607
Win10 17030xADwin10-1703
Win10 17090xAEwin10-1709
Win10 18030xAFwin10-1803
Win10 18090xAFwin10-1809
Win10 19030xB0win10-1903
Win10 19090xB0win10-1909
Win10 20040xB4win10-2004
Win10 20H20xB4win10-20h2
Win10 21H10xB4win10-21h1
Win10 21H20xB5win10-21h2
Win10 22H20xB5win10-22h2
Win11 21H20xB8win11-21h2
Win11 22H20xB9win11-22h2
Win11 23H20xB9win11-23h2
Win11 24H20xBBwin11-24h2
Server 20160xAAwinserver-2016
Server 20190xAFwinserver-2019
Server 20220xB7winserver-2022
Server 20250xBBwinserver-2025

Module noyau

ntoskrnl.exeNtCreateNamedPipeFile

APIs liées

CreateNamedPipeWConnectNamedPipeDisconnectNamedPipeWaitNamedPipeWCallNamedPipeWNtFsControlFileNtCreateFile

Stub du syscall

4C 8B D1            mov r10, rcx
B8 BB 00 00 00      mov eax, 0xBB
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

`NtCreateNamedPipeFile` est la plus grosse Native API en nombre de paramètres (14) et la base de `CreateNamedPipeW`. Les noms de pipe vivent sous `\Device\NamedPipe\` ; la forme user-mode est `\\.\pipe\<nom>` ou, à distance, `\\<host>\pipe\<nom>`. Les ouvertures distantes passent par SMB et sont soumises aux paramètres firewall/NetBIOS — c'est précisément pour cela que le beacon SMB de Cobalt Strike écoute sur un pipe nommé plutôt qu'un socket TCP. Le SSN change toutes les deux ou trois feature updates (`0xA8` sur Win10 1507 → `0xBB` sur Win11 24H2), donc le shellcode portable résout dynamiquement.

Usage courant par les malwares

Les pipes nommées sont le canal IPC *de facto* du post-exploit moderne : - **Beacon SMB Cobalt Strike** : les beacons pairs se connectent via un pipe serveur (par défaut `\\.\pipe\msagent_xx`, `\\.\pipe\status_xx`, etc.). Le trafic C2 est encapsulé dans la pipe sans toucher l'adaptateur réseau du host de sortie. - **Transport named-pipe Sliver** : même idée — communication implant↔implant pour le mouvement latéral sans ouvrir de port TCP. - **Services type PsExec** créent `\pipe\psexesvc` pour le retour du canal de commande. - De nombreuses familles ransomware (Conti, BlackCat) coordonnent leurs workers de chiffrement via une pipe pour centraliser le reporting d'avancement. L'attaquant choisit un nom qui mime un service Microsoft légitime (`\pipe\lsass`, `\pipe\spoolss`, `\pipe\mojo.*`) pour se fondre dans le bruit IPC/navigateur.

Opportunités de détection

Sysmon **Event ID 17 (PipeEvent: Pipe Created)** et **18 (PipeEvent: Pipe Connected)** sont les détections les plus parlantes pour ce syscall. Noms de pipe inhabituels — suffixes aléatoires, noms GUID, `msagent_*` sur un hôte non visé par Cobalt, ou ouvertures `\pipe\` depuis des processus inattendus (notepad.exe, wmiprvse.exe) — sont de forts indicateurs de beacon SMB ou d'implant peer-to-peer. Le provider ETW `Microsoft-Windows-Kernel-File` couvre les create/open de FO de pipe. Les EDR alertent aussi sur la séquence `NtCreateNamedPipeFile` suivie de `NtFsControlFile(FSCTL_PIPE_LISTEN)` depuis un processus non service.

Exemples de syscalls directs

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtCreateNamedPipeFile (SSN 0xBB on Win11 24H2)
NtCreateNamedPipeFile PROC
    mov  r10, rcx          ; FileHandle
    mov  eax, 0BBh         ; SSN — version-sensitive, resolve dynamically
    syscall
    ret
NtCreateNamedPipeFile ENDP

cCobalt-Strike-style SMB beacon listener

// Create \\.\pipe\msagent_42 as a message-mode server pipe.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI *pNtCreateNamedPipeFile)(
    PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
    ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, PLARGE_INTEGER);

HANDLE OpenBeaconPipe(void) {
    UNICODE_STRING name;
    RtlInitUnicodeString(&name, L"\\??\\pipe\\msagent_42");
    OBJECT_ATTRIBUTES oa;
    InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL);
    IO_STATUS_BLOCK iosb = {0};
    LARGE_INTEGER timeout; timeout.QuadPart = -50LL * 10000LL; // 50 ms
    HANDLE hPipe = NULL;

    pNtCreateNamedPipeFile fn = (pNtCreateNamedPipeFile)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtCreateNamedPipeFile");
    fn(&hPipe,
       GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
       &oa, &iosb,
       FILE_SHARE_READ | FILE_SHARE_WRITE,
       FILE_CREATE,
       FILE_SYNCHRONOUS_IO_NONALERT,
       1 /* FILE_PIPE_MESSAGE_TYPE   */,
       1 /* FILE_PIPE_MESSAGE_MODE   */,
       0 /* FILE_PIPE_QUEUE_OP       */,
       0xFF /* PIPE_UNLIMITED_INSTANCES */,
       0x1000, 0x1000,
       &timeout);
    return hPipe;
}

rustwindows-sys wrapper

// Cargo: windows-sys = "0.59", features = ["Wdk_Storage_FileSystem", "Win32_System_IO"]
use std::ptr::null_mut;
use windows_sys::Wdk::Storage::FileSystem::NtCreateNamedPipeFile;
use windows_sys::Win32::Storage::FileSystem::*;
use windows_sys::Win32::System::IO::IO_STATUS_BLOCK;
use windows_sys::Win32::System::WindowsProgramming::*;
use windows_sys::Wdk::Foundation::OBJECT_ATTRIBUTES;

pub fn create_message_pipe(_name: &str) -> isize {
    let mut handle: isize = 0;
    let mut iosb: IO_STATUS_BLOCK = unsafe { std::mem::zeroed() };
    let timeout: i64 = -50 * 10_000; // 50 ms relative
    // ObjectAttributes / UNICODE_STRING construction elided — see ntdll helpers.
    let oa: OBJECT_ATTRIBUTES = unsafe { std::mem::zeroed() };
    unsafe {
        NtCreateNamedPipeFile(
            &mut handle,
            (GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE) as u32,
            &oa, &mut iosb,
            (FILE_SHARE_READ | FILE_SHARE_WRITE) as u32,
            FILE_CREATE,
            FILE_SYNCHRONOUS_IO_NONALERT,
            1, 1, 0, 0xFF, 0x1000, 0x1000,
            &timeout as *const _ as *mut _,
        );
    }
    handle
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20