NtCreateNamedPipeFile
Erzeugt das Server-Ende einer Named-Pipe im Geräte-Namespace \Device\NamedPipe.
Prototyp
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 );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | PHANDLE | out | Empfängt das Handle auf das neu erzeugte Server-Ende der Named-Pipe. |
| DesiredAccess | ULONG | in | Zugriffsmaske, typischerweise GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Benennt die Pipe unter \Device\NamedPipe (z. B. \??\pipe\msagent_xx) und liefert den SECURITY_DESCRIPTOR. |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Empfängt den finalen NTSTATUS und Informationscode (FILE_CREATED / FILE_OPENED). |
| ShareAccess | ULONG | in | FILE_SHARE_*-Flags steuern die Semantik konkurrierender Öffnungen der Named-Pipe. |
| CreateDisposition | ULONG | in | FILE_CREATE, FILE_OPEN oder FILE_OPEN_IF; Verhalten falls der Name existiert. |
| CreateOptions | ULONG | in | FILE_SYNCHRONOUS_IO_NONALERT etc. — gleicher Flag-Satz wie bei NtCreateFile. |
| NamedPipeType | ULONG | in | FILE_PIPE_BYTE_STREAM_TYPE oder FILE_PIPE_MESSAGE_TYPE — Übertragungsformat. |
| ReadMode | ULONG | in | FILE_PIPE_BYTE_STREAM_MODE oder FILE_PIPE_MESSAGE_MODE für Reads. |
| CompletionMode | ULONG | in | FILE_PIPE_QUEUE_OPERATION (blockierend) oder FILE_PIPE_COMPLETE_OPERATION (sofortige Rückkehr). |
| MaximumInstances | ULONG | in | Maximale gleichzeitige Server-Instanzen dieses Pipe-Namens; PIPE_UNLIMITED_INSTANCES = 0xFF. |
| InboundQuota | ULONG | in | Puffergröße für Client→Server-Daten in Byte. |
| OutboundQuota | ULONG | in | Puffergröße für Server→Client-Daten in Byte. |
| DefaultTimeout | PLARGE_INTEGER | in | Standard-Timeout für blockierende Operationen (100-ns-Einheiten, negativ = relativ). NULL = 50 ms. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0xA8 | win10-1507 |
| Win10 1607 | 0xAA | win10-1607 |
| Win10 1703 | 0xAD | win10-1703 |
| Win10 1709 | 0xAE | win10-1709 |
| Win10 1803 | 0xAF | win10-1803 |
| Win10 1809 | 0xAF | win10-1809 |
| Win10 1903 | 0xB0 | win10-1903 |
| Win10 1909 | 0xB0 | win10-1909 |
| Win10 2004 | 0xB4 | win10-2004 |
| Win10 20H2 | 0xB4 | win10-20h2 |
| Win10 21H1 | 0xB4 | win10-21h1 |
| Win10 21H2 | 0xB5 | win10-21h2 |
| Win10 22H2 | 0xB5 | win10-22h2 |
| Win11 21H2 | 0xB8 | win11-21h2 |
| Win11 22H2 | 0xB9 | win11-22h2 |
| Win11 23H2 | 0xB9 | win11-23h2 |
| Win11 24H2 | 0xBB | win11-24h2 |
| Server 2016 | 0xAA | winserver-2016 |
| Server 2019 | 0xAF | winserver-2019 |
| Server 2022 | 0xB7 | winserver-2022 |
| Server 2025 | 0xBB | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
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
Undokumentierte Hinweise
`NtCreateNamedPipeFile` ist mit 14 Parametern die größte einzelne Native API und Grundlage von `CreateNamedPipeW`. Pipe-Namen liegen unter `\Device\NamedPipe\`; die User-Mode-Form ist `\\.\pipe\<Name>` oder remote `\\<Host>\pipe\<Name>`. Remote-Öffnungen laufen über SMB und unterliegen Firewall/NetBIOS — genau deshalb hört Cobalt Strikes SMB-Beacon auf einer Named-Pipe statt einem TCP-Socket. Der SSN ändert sich alle zwei bis drei Feature-Updates (`0xA8` auf Win10 1507 → `0xBB` auf Win11 24H2); portabler Shellcode löst dynamisch auf.
Häufige Malware-Nutzung
Named Pipes sind der *de-facto* IPC-Kanal moderner Post-Exploitation: - **Cobalt-Strike-SMB-Beacon**: Peer-Beacons verbinden sich über eine Server-Named-Pipe (default `\\.\pipe\msagent_xx`, `\\.\pipe\status_xx` etc.). C2-Verkehr läuft tunneled in der Pipe, ohne den Netzwerkadapter des Egress-Hosts zu berühren. - **Sliver Named-Pipe-Transport**: gleiche Idee — Implant↔Implant-Kommunikation für Lateral Movement, ohne neue TCP-Ports zu öffnen. - **PsExec-artige Dienste** legen `\pipe\psexesvc` für den Befehlsrückkanal an. - Viele Ransomware-Familien (Conti, BlackCat) koordinieren ihre Verschlüsselungs-Worker über eine Pipe, um Fortschrittsmeldungen zu zentralisieren. Angreifer wählen Namen, die legitime Microsoft-Dienste nachahmen (`\pipe\lsass`, `\pipe\spoolss`, `\pipe\mojo.*`), um im IPC-/Browser-Rauschen unterzugehen.
Erkennungsmöglichkeiten
Sysmon **Event ID 17 (PipeEvent: Pipe Created)** und **18 (PipeEvent: Pipe Connected)** sind die ergiebigsten Detektionen für diesen Syscall. Ungewöhnliche Pipe-Namen — zufällige Suffixe, GUID-artige Namen, `msagent_*` auf einem nicht von Cobalt anvisierten Host, oder `\pipe\`-Öffnungen aus unerwarteten Prozessen (notepad.exe, wmiprvse.exe) — sind starke Indikatoren für SMB-Beacons oder Peer-to-Peer-Implants. Der ETW-Provider `Microsoft-Windows-Kernel-File` deckt Create/Open der Pipe-File-Objekte ab. EDRs alarmieren auch auf das Muster `NtCreateNamedPipeFile` gefolgt von `NtFsControlFile(FSCTL_PIPE_LISTEN)` aus einem Nicht-Dienst-Prozess.
Direkte Syscall-Beispiele
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 ENDPcCobalt-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
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20