NtCreateFile
Erstellt oder öffnet eine Datei, ein Verzeichnis, ein Gerät oder eine benannte Pipe — der erste Disk-Aufruf jedes Droppers.
Prototyp
NTSTATUS NtCreateFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | PHANDLE | out | Erhält das Handle auf die erstellte oder geöffnete Datei. |
| DesiredAccess | ACCESS_MASK | in | Zugriffsmaske, z. B. GENERIC_WRITE | SYNCHRONIZE, FILE_GENERIC_READ, DELETE. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | OBJECT_ATTRIBUTES mit dem NT-Pfad (z. B. \??\C:\Windows\Temp\a.exe). |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Erhält finalen NTSTATUS und das Information-Feld (FILE_CREATED, FILE_OPENED, FILE_OVERWRITTEN…). |
| AllocationSize | PLARGE_INTEGER | in | Optionale initiale Größe. NULL überlässt sie dem Dateisystem. |
| FileAttributes | ULONG | in | Attribute neuer Dateien: FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_SYSTEM. |
| ShareAccess | ULONG | in | Sharing-Modus: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE oder 0 für exklusiv. |
| CreateDisposition | ULONG | in | Verhalten bei existierender Datei: FILE_CREATE, FILE_OPEN, FILE_OPEN_IF, FILE_OVERWRITE, FILE_OVERWRITE_IF, FILE_SUPERSEDE. |
| CreateOptions | ULONG | in | Optionen: FILE_SYNCHRONOUS_IO_NONALERT, FILE_NON_DIRECTORY_FILE, FILE_DELETE_ON_CLOSE… |
| EaBuffer | PVOID | in | Extended-Attributes-Puffer. Üblicherweise NULL. |
| EaLength | ULONG | in | Größe von EaBuffer in Bytes. 0, wenn EaBuffer NULL ist. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x55 | win10-1507 |
| Win10 1607 | 0x55 | win10-1607 |
| Win10 1703 | 0x55 | win10-1703 |
| Win10 1709 | 0x55 | win10-1709 |
| Win10 1803 | 0x55 | win10-1803 |
| Win10 1809 | 0x55 | win10-1809 |
| Win10 1903 | 0x55 | win10-1903 |
| Win10 1909 | 0x55 | win10-1909 |
| Win10 2004 | 0x55 | win10-2004 |
| Win10 20H2 | 0x55 | win10-20h2 |
| Win10 21H1 | 0x55 | win10-21h1 |
| Win10 21H2 | 0x55 | win10-21h2 |
| Win10 22H2 | 0x55 | win10-22h2 |
| Win11 21H2 | 0x55 | win11-21h2 |
| Win11 22H2 | 0x55 | win11-22h2 |
| Win11 23H2 | 0x55 | win11-23h2 |
| Win11 24H2 | 0x55 | win11-24h2 |
| Server 2016 | 0x55 | winserver-2016 |
| Server 2019 | 0x55 | winserver-2019 |
| Server 2022 | 0x55 | winserver-2022 |
| Server 2025 | 0x55 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 55 00 00 00 mov eax, 0x55 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
NtCreateFile nimmt 11 Parameter — mehr als jeder andere häufig missbrauchte Syscall — und ist der Einstieg unter `CreateFileW`, `OpenFile`, `_open` und den meisten CRT-Helfern, die das Dateisystem berühren. Die SSN `0x55` ist seit Windows 7 unverändert. Der Pfad lebt im NT-Namensraum (`\??\C:\Pfad` oder `\Device\HarddiskVolume3\Pfad`); ein Nicht-Win32-Pfad ist ein gängiger Trick, um an DOS-Pfade gebundene Minifilter-Regeln auszuhebeln. Unter x64 wandern nur die ersten vier Parameter durch Register (RCX, RDX, R8, R9) — der Rest liegt auf dem Stack hinter dem 32-Byte-Home-Space, was beim Selberbauen eines Stubs zählt.
Häufige Malware-Nutzung
Die universelle Dropper-Primitive: Zweitstufen-Payloads in `%PROGRAMDATA%`, `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\`, `%APPDATA%\Microsoft\Templates\Normal.dotm` (Office-Template-Persistenz, T1137.001) oder `C:\Users\Public\` schreiben, um nutzerspezifische Roaming-Profile zu meiden. Mit `FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM` und führendem `.` verschwindet die Datei aus dem Standard-Explorer. `FILE_FLAG_DELETE_ON_CLOSE` (über die CreateOption `FILE_DELETE_ON_CLOSE`) bedient sich-selbst-löschende Dropper, und der Zugriff auf `\\.\PHYSICALDRIVE0` ist die Tür für MBR-überschreibende Wiper (Petya, HermeticWiper).
Erkennungsmöglichkeiten
Sysmon Event ID 11 (FileCreate) ist der Eckpfeiler — feuert mit Image-Pfad des Erzeugers und dem vollen Zielpfad. Event ID 23 (FileDelete) und 26 (FileDeleteDetected) erfassen Selbstlöschung. ETW Microsoft-Windows-Kernel-File (`{EDD08927-9CC4-4E65-B970-C2560FB5C289}`) liefert dasselbe ohne Sysmon. EDR-Minifilter-Treiber (FltMgr) sehen jedes NtCreateFile inklusive Pre- und Post-Create-Callbacks — die meisten EDRs nutzen diesen Weg statt User-Mode-Hooks, also verbergen direkte Syscalls Dateidrops *nicht*. Jagen auf Schreibvorgänge in Startup-Ordnern, `Templates\Normal.dotm`, IFEO-nahe Pfade und `\Device\PhysicalDriveN`-Öffnungen durch Nicht-System-Prozesse.
Direkte Syscall-Beispiele
cDrop a hidden payload to %PROGRAMDATA%
// Create C:\ProgramData\impl.bin hidden+system, overwrite if exists.
UNICODE_STRING path;
RtlInitUnicodeString(&path, L"\\??\\C:\\ProgramData\\impl.bin");
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &path, OBJ_CASE_INSENSITIVE, NULL, NULL);
IO_STATUS_BLOCK iosb = {0};
HANDLE hFile = NULL;
NTSTATUS s = NtCreateFile(
&hFile,
GENERIC_WRITE | SYNCHRONIZE,
&oa,
&iosb,
NULL, // AllocationSize
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
FILE_SHARE_READ,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
NULL, 0);asmDirect stub (SSN 0x55) — stack args
; NtCreateFile has 11 args. Caller pushes args 5..11 on the stack;
; the syscall stub itself is the canonical 4-instr form.
NtCreateFile PROC
mov r10, rcx
mov eax, 55h
syscall
ret
NtCreateFile ENDPrustSelf-deleting marker file
// Sets FILE_DELETE_ON_CLOSE so the file vanishes when the handle is closed.
use ntapi::ntioapi::{NtCreateFile, IO_STATUS_BLOCK};
use ntapi::ntrtl::RtlInitUnicodeString;
use winapi::shared::ntdef::{OBJECT_ATTRIBUTES, OBJ_CASE_INSENSITIVE, UNICODE_STRING};
use winapi::um::winnt::{DELETE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, SYNCHRONIZE};
const FILE_CREATE: u32 = 0x2;
const FILE_SYNCHRONOUS_IO_NONALERT: u32 = 0x20;
const FILE_DELETE_ON_CLOSE: u32 = 0x1000;
const FILE_NON_DIRECTORY_FILE: u32 = 0x40;
pub unsafe fn touch_ephemeral(nt_path: *const u16) {
let mut us: UNICODE_STRING = core::mem::zeroed();
RtlInitUnicodeString(&mut us, nt_path);
let mut oa = OBJECT_ATTRIBUTES {
Length: core::mem::size_of::<OBJECT_ATTRIBUTES>() as u32,
RootDirectory: core::ptr::null_mut(),
ObjectName: &mut us,
Attributes: OBJ_CASE_INSENSITIVE,
SecurityDescriptor: core::ptr::null_mut(),
SecurityQualityOfService: core::ptr::null_mut(),
};
let mut iosb: IO_STATUS_BLOCK = core::mem::zeroed();
let mut h = core::ptr::null_mut();
NtCreateFile(
&mut h,
DELETE | SYNCHRONIZE,
&mut oa,
&mut iosb,
core::ptr::null_mut(),
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_CREATE,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE,
core::ptr::null_mut(),
0,
);
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20