NtOpenFile
Öffnet ein Handle auf eine vorhandene Datei oder ein Gerät — das leichte No-Create-Pendant zu NtCreateFile.
Prototyp
NTSTATUS NtOpenFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | PHANDLE | out | Empfängt das Handle auf die geöffnete Datei oder das Gerät bei Erfolg. |
| DesiredAccess | ACCESS_MASK | in | Angeforderte Zugriffsrechte (FILE_READ_DATA, FILE_GENERIC_READ, SYNCHRONIZE, READ_CONTROL usw.). |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | NT-Namespace-Pfad, z. B. \??\C:\Windows\System32\config\SAM oder \Device\HarddiskVolume1\... |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Empfängt den finalen NTSTATUS und das Information-Feld (FILE_OPENED hier, vs FILE_CREATED bei NtCreateFile). |
| ShareAccess | ULONG | in | Maske FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE für gleichzeitige Öffner. |
| OpenOptions | ULONG | in | FILE_SYNCHRONOUS_IO_NONALERT, FILE_NON_DIRECTORY_FILE, FILE_OPEN_REPARSE_POINT, FILE_OPEN_FOR_BACKUP_INTENT usw. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x33 | win10-1507 |
| Win10 1607 | 0x33 | win10-1607 |
| Win10 1703 | 0x33 | win10-1703 |
| Win10 1709 | 0x33 | win10-1709 |
| Win10 1803 | 0x33 | win10-1803 |
| Win10 1809 | 0x33 | win10-1809 |
| Win10 1903 | 0x33 | win10-1903 |
| Win10 1909 | 0x33 | win10-1909 |
| Win10 2004 | 0x33 | win10-2004 |
| Win10 20H2 | 0x33 | win10-20h2 |
| Win10 21H1 | 0x33 | win10-21h1 |
| Win10 21H2 | 0x33 | win10-21h2 |
| Win10 22H2 | 0x33 | win10-22h2 |
| Win11 21H2 | 0x33 | win11-21h2 |
| Win11 22H2 | 0x33 | win11-22h2 |
| Win11 23H2 | 0x33 | win11-23h2 |
| Win11 24H2 | 0x33 | win11-24h2 |
| Server 2016 | 0x33 | winserver-2016 |
| Server 2019 | 0x33 | winserver-2019 |
| Server 2022 | 0x33 | winserver-2022 |
| Server 2025 | 0x33 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 33 00 00 00 mov eax, 0x33 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
NtOpenFile ist funktional äquivalent zu `NtCreateFile` mit `CreateDisposition = FILE_OPEN`, hat aber weniger Argumente — keine Allocation-Size, keine Extended Attributes, keine File Attributes. Dateien anlegen kann sie nicht. Die SSN `0x33` ist seit Windows 10 1507 stabil. Der Win32-Wrapper `CreateFileW` dispatcht stets auf `NtCreateFile`; User-Mode-Code, der NtOpenFile bevorzugt, umgeht den Create-Pfad bewusst, um EDR-Hooks zu meiden, die sich auf NtCreateFile konzentrieren, oder hält die Aufruf-Signatur für Direkt-Syscall-Stubs klein.
Häufige Malware-Nutzung
Anwendungsfälle clustern sich um **verdeckte Dateisystem-Enumeration und -Lese-Operationen**. NtOpenFile mit NtQueryDirectoryFile und NtReadFile zu kombinieren erlaubt einem Loader, Verzeichnisse zu durchwandern und Konfigurations- / Zieldateien vollständig über die Nt*-Fläche zu schlürfen, ohne `kernel32!CreateFileW`- und `FindFirstFileW`-Hooks zu treffen, die User-Mode-EDRs häufig inlinen. `FILE_OPEN_FOR_BACKUP_INTENT` plus SeBackupPrivilege erlaubt dem Aufruf zudem, DACLs beim Lesen zu umgehen — nützlich für Hive-Staging-Ketten (`\??\C:\Windows\System32\config\SAM` als SYSTEM direkt öffnen, ohne VSS). NtOpenFile ist auch die bevorzugte Wahl zum Öffnen von Device-Objekten (`\Device\PhysicalDrive0`, `\??\PIPE\...`) in Tools, die explizit den NT-Pfad nutzen wollen.
Erkennungsmöglichkeiten
NtOpenFile ist zu häufig, um direkt darauf zu alarmieren — jeder Prozess macht viele Aufrufe. Das diskriminierende Signal ist der *Zielpfad* kombiniert mit dem *Aufrufer*: Ein Nicht-System-Prozess, der `\Device\PhysicalDrive*`, `\??\C:\Windows\System32\config\SAM`, `\??\C:\Windows\NTDS\ntds.dit` oder einen LSASS-bezogenen Pfad öffnet, ist hochkonfident bösartig. Sysmon Event 11 deckt File-*Creates* ab, nicht reine Opens; für Opens sind die ETW-Provider Microsoft-Windows-Kernel-File und Microsoft-Windows-Threat-Intelligence die primäre Telemetrie, ergänzt durch EDR-Mini-Filter-Callbacks auf IRP_MJ_CREATE-Ebene.
Direkte Syscall-Beispiele
asmx64 direct stub
; Direct syscall stub for NtOpenFile (SSN 0x33, stable since Win10 1507)
NtOpenFile PROC
mov r10, rcx ; FileHandle
mov eax, 33h ; SSN
syscall
ret
NtOpenFile ENDPcStealthy file open + read (Nt* only)
// Open a file via the NT namespace and read its content without touching
// kernel32!CreateFileW / ReadFile — useful for loaders that want to skip
// common user-mode hook surfaces.
#include <windows.h>
#include <winternl.h>
#define FILE_OPEN 0x00000001
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
int ReadViaNtOpen(LPCWSTR ntpath, void *buf, ULONG len) {
UNICODE_STRING us; RtlInitUnicodeString(&us, ntpath);
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &us, OBJ_CASE_INSENSITIVE, NULL, NULL);
IO_STATUS_BLOCK iosb = {0};
HANDLE h = NULL;
NTSTATUS s = NtOpenFile(&h, FILE_GENERIC_READ | SYNCHRONIZE,
&oa, &iosb,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (s < 0) return s;
s = NtReadFile(h, NULL, NULL, NULL, &iosb, buf, len, NULL, NULL);
NtClose(h);
return (int)iosb.Information;
}rustwindows-sys NtOpenFile call
// Cargo: windows-sys = { version = "0.59", features = [
// "Win32_Foundation", "Wdk_Foundation", "Wdk_Storage_FileSystem",
// "Win32_System_WindowsProgramming",
// ] }
use windows_sys::Wdk::Storage::FileSystem::NtOpenFile;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::WindowsProgramming::OBJECT_ATTRIBUTES;
use windows_sys::Wdk::Foundation::OBJECT_ATTRIBUTES as OA;
use windows_sys::Win32::System::IO::IO_STATUS_BLOCK;
unsafe fn open_for_read(oa: *mut OA) -> Option<HANDLE> {
let mut h: HANDLE = std::ptr::null_mut();
let mut iosb: IO_STATUS_BLOCK = std::mem::zeroed();
let s = NtOpenFile(
&mut h,
0x80000000 /* GENERIC_READ */ | 0x00100000 /* SYNCHRONIZE */,
oa as *mut OBJECT_ATTRIBUTES,
&mut iosb,
0x00000003 /* SHARE_READ|WRITE */,
0x00000020 /* FILE_SYNCHRONOUS_IO_NONALERT */,
);
if s == 0 { Some(h) } else { None }
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20