NtCreateMailslotFile
Creates the server side of a mailslot — a legacy, one-way, datagram-style IPC primitive accessed via \Device\Mailslot.
Prototype
NTSTATUS NtCreateMailslotFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG CreateOptions, ULONG MailslotQuota, ULONG MaximumMessageSize, PLARGE_INTEGER ReadTimeout );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | PHANDLE | out | Receives the handle to the newly created mailslot server endpoint. |
| DesiredAccess | ACCESS_MASK | in | Access rights requested — typically GENERIC_READ | SYNCHRONIZE for a server. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Names the mailslot, typically \??\mailslot\<name> (corresponds to \\.\mailslot\<name>). |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Receives FILE_CREATED on success and the I/O completion status. |
| CreateOptions | ULONG | in | Reserved create-time flags — almost always 0 for mailslots. |
| MailslotQuota | ULONG | in | Maximum bytes that can be queued in the slot at once. 0 = system default. |
| MaximumMessageSize | ULONG | in | Largest message a single write may carry. 0 means any size up to MailslotQuota. |
| ReadTimeout | PLARGE_INTEGER | in | Default timeout for blocking reads. NULL = wait forever, 0 = return immediately. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1507 | 0xA6 | win10-1507 |
| Win10 1607 | 0xA8 | win10-1607 |
| Win10 1703 | 0xAB | win10-1703 |
| Win10 1709 | 0xAC | win10-1709 |
| Win10 1803 | 0xAD | win10-1803 |
| Win10 1809 | 0xAD | win10-1809 |
| Win10 1903 | 0xAE | win10-1903 |
| Win10 1909 | 0xAE | win10-1909 |
| Win10 2004 | 0xB2 | win10-2004 |
| Win10 20H2 | 0xB2 | win10-20h2 |
| Win10 21H1 | 0xB2 | win10-21h1 |
| Win10 21H2 | 0xB3 | win10-21h2 |
| Win10 22H2 | 0xB3 | win10-22h2 |
| Win11 21H2 | 0xB6 | win11-21h2 |
| Win11 22H2 | 0xB7 | win11-22h2 |
| Win11 23H2 | 0xB7 | win11-23h2 |
| Win11 24H2 | 0xB9 | win11-24h2 |
| Server 2016 | 0xA8 | winserver-2016 |
| Server 2019 | 0xAD | winserver-2019 |
| Server 2022 | 0xB5 | winserver-2022 |
| Server 2025 | 0xB9 | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 B9 00 00 00 mov eax, 0xB9 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
Undocumented notes
Mailslots are a connectionless, one-way IPC — the *server* creates the slot via NtCreateMailslotFile and reads incoming datagrams; *clients* simply open `\\<host>\mailslot\<name>` with NtOpenFile/NtCreateFile and write to it. They predate named pipes and are implemented by mailslot.sys / mrxsmb.sys (cross-host delivery rides SMB). Messages can be broadcast to a domain-wide name (`\\*\mailslot\foo`), though that path is heavily restricted on modern domains. Maximum cross-network message size is 424 bytes; local-only mailslots can be much larger.
Common malware usage
Mailslots are an *OPSEC-favourable* IPC because almost no modern security stack inspects them. Cobalt Strike historically offered a mailslot SMB transport for beacon-to-beacon delivery — it's lower fidelity than named pipes but largely invisible to EDRs that hook NtCreateNamedPipeFile / FltMgr name-callbacks for pipes. Niche real-world use today: covert local IPC between cooperating implants in the same lateral-movement chain, where named pipes would draw immediate Sysmon Event 17/18 attention. Genuine modern named-malware-family use is rare; the asymmetric detection gap is the main draw.
Detection opportunities
Detection is genuinely sparse. Sysmon has no MailslotEvent (Events 17 / 18 cover named pipes only). ETW Microsoft-Windows-Kernel-File emits Create events with a `\Device\Mailslot\` path — write rules against that prefix in EDR file-create hooks. CmRegisterCallbackEx doesn't apply (no registry involvement); the right hookpoint is FltRegisterFilter against mailslot.sys's file system minifilter chain. Hunt query: any process creating an object under `\Device\Mailslot\` outside of `lsass.exe` (NETLOGON), `services.exe`, or `winlogon.exe` is worth investigating.
Direct syscall examples
cMinimal mailslot server
// Creates \\.\mailslot\implant_chan as a passive receiver.
UNICODE_STRING name;
RtlInitUnicodeString(&name, L"\\??\\mailslot\\implant_chan");
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL);
IO_STATUS_BLOCK iosb;
HANDLE hSlot = NULL;
NTSTATUS st = NtCreateMailslotFile(
&hSlot,
GENERIC_READ | SYNCHRONIZE,
&oa,
&iosb,
0, // CreateOptions
0, // MailslotQuota — system default
1024, // MaximumMessageSize
NULL // ReadTimeout — wait forever
);asmx64 direct stub (Win11 24H2 SSN 0xB9)
NtCreateMailslotFile PROC
mov r10, rcx
mov eax, 0B9h
syscall
ret
NtCreateMailslotFile ENDPrustwindows-sys receiver
// Cargo: windows-sys = "0.59" (Win32_Storage_FileSystem, Win32_Foundation)
use windows_sys::Win32::Storage::FileSystem::*;
let h = unsafe {
CreateMailslotW(
w!("\\\\.\\mailslot\\implant_chan"),
1024, // nMaxMessageSize
MAILSLOT_WAIT_FOREVER, // lReadTimeout
null_mut(), // lpSecurityAttributes
)
};
// CreateMailslotW funnels into NtCreateMailslotFile.MITRE ATT&CK mappings
Last verified: 2026-05-20