> Windows Syscalls
ntoskrnl.exeT1571T1090T1559

NtCreateNamedPipeFile

Crea el extremo servidor de un canal con nombre en el espacio de nombres \Device\NamedPipe.

Prototipo

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
);

Argumentos

NameTypeDirDescription
FileHandlePHANDLEoutRecibe el handle al extremo servidor recién creado del canal con nombre.
DesiredAccessULONGinMáscara de acceso, típicamente GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE.
ObjectAttributesPOBJECT_ATTRIBUTESinNombra el canal bajo \Device\NamedPipe (p. ej. \??\pipe\msagent_xx) y aporta el SECURITY_DESCRIPTOR.
IoStatusBlockPIO_STATUS_BLOCKoutRecibe el NTSTATUS final y el código de información (FILE_CREATED / FILE_OPENED).
ShareAccessULONGinBanderas FILE_SHARE_* que controlan la semántica de apertura concurrente del canal.
CreateDispositionULONGinFILE_CREATE, FILE_OPEN o FILE_OPEN_IF; comportamiento si el nombre ya existe.
CreateOptionsULONGinFILE_SYNCHRONOUS_IO_NONALERT y similares — mismo conjunto que NtCreateFile.
NamedPipeTypeULONGinFILE_PIPE_BYTE_STREAM_TYPE o FILE_PIPE_MESSAGE_TYPE — formato de transporte.
ReadModeULONGinFILE_PIPE_BYTE_STREAM_MODE o FILE_PIPE_MESSAGE_MODE para las lecturas.
CompletionModeULONGinFILE_PIPE_QUEUE_OPERATION (bloqueante) o FILE_PIPE_COMPLETE_OPERATION (retorno inmediato).
MaximumInstancesULONGinNúmero máximo de instancias servidoras concurrentes para este nombre; PIPE_UNLIMITED_INSTANCES = 0xFF.
InboundQuotaULONGinTamaño del búfer cliente→servidor, en bytes.
OutboundQuotaULONGinTamaño del búfer servidor→cliente, en bytes.
DefaultTimeoutPLARGE_INTEGERinTiempo de espera por defecto para operaciones bloqueantes (unidades de 100 ns, negativo = relativo). NULL = 50 ms.

IDs de syscalls por versión de Windows

Versión 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

Módulo del kernel

ntoskrnl.exeNtCreateNamedPipeFile

APIs relacionadas

CreateNamedPipeWConnectNamedPipeDisconnectNamedPipeWaitNamedPipeWCallNamedPipeWNtFsControlFileNtCreateFile

Stub del 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

Notas no documentadas

`NtCreateNamedPipeFile` es la mayor Native API por número de parámetros (14) y la base de `CreateNamedPipeW`. Los nombres de pipe viven bajo `\Device\NamedPipe\`; la forma user-mode es `\\.\pipe\<nombre>` o, remoto, `\\<host>\pipe\<nombre>`. Las aperturas remotas viajan por SMB y dependen del firewall/NetBIOS — por eso el beacon SMB de Cobalt Strike escucha en pipe en vez de en un socket TCP. El SSN cambia cada dos o tres feature updates (`0xA8` en Win10 1507 → `0xBB` en Win11 24H2), por lo que el shellcode portable lo resuelve dinámicamente.

Uso común por malware

Las named pipes son el canal IPC *de facto* del post-explotación moderno: - **Beacon SMB Cobalt Strike**: beacons pares se conectan a través de un pipe servidor (por defecto `\\.\pipe\msagent_xx`, `\\.\pipe\status_xx`, etc.). El tráfico C2 va encapsulado en el pipe sin tocar el adaptador de red del host de salida. - **Transporte named-pipe Sliver**: la misma idea — comunicación implante↔implante para movimiento lateral sin abrir nuevos puertos TCP. - **Servicios tipo PsExec** crean `\pipe\psexesvc` para el canal de retorno de comandos. - Muchas familias ransomware (Conti, BlackCat) coordinan sus workers de cifrado por una pipe para centralizar el reporte de progreso. El atacante elige un nombre que imita un servicio Microsoft legítimo (`\pipe\lsass`, `\pipe\spoolss`, `\pipe\mojo.*`) para mezclarse con el ruido IPC/navegador.

Oportunidades de detección

Sysmon **Event ID 17 (PipeEvent: Pipe Created)** y **18 (PipeEvent: Pipe Connected)** son las detecciones más informativas para este syscall. Nombres de pipe raros — sufijos aleatorios, nombres GUID, `msagent_*` en un host no objetivo de Cobalt, o aperturas `\pipe\` desde procesos inesperados (notepad.exe, wmiprvse.exe) — son indicadores fuertes de beacon SMB o implante peer-to-peer. El proveedor ETW `Microsoft-Windows-Kernel-File` cubre create/open de FO de pipe. Los EDR también alertan sobre la secuencia `NtCreateNamedPipeFile` seguida de `NtFsControlFile(FSCTL_PIPE_LISTEN)` desde un proceso no servicio.

Ejemplos de syscalls directos

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
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20