NtReadFile
Liest Bytes aus einer Datei, einem Gerät, einer benannten Pipe oder einer gemappten Section in einen User-Puffer — Kernel-Primitive hinter ReadFile.
Prototyp
NTSTATUS NtReadFile( HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | HANDLE | in | Handle aus NtCreateFile/NtOpenFile mit FILE_READ_DATA- oder GENERIC_READ-Zugriff. |
| Event | HANDLE | in | Optionales Event-Handle, das bei asynchroner Fertigstellung gesetzt wird. NULL für synchrones I/O. |
| ApcRoutine | PIO_APC_ROUTINE | in | Optionale User-Mode-APC-Routine, die bei Fertigstellung eingereiht wird. NULL für synchrone Aufrufe. |
| ApcContext | PVOID | in | Kontext-Zeiger, der an ApcRoutine übergeben wird. Üblicherweise NULL. |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Erhält finalen NTSTATUS und Information-Feld mit den tatsächlich gelesenen Bytes. |
| Buffer | PVOID | out | User-Mode-Puffer, der die Daten aufnimmt. Muss mindestens Length Bytes groß sein. |
| Length | ULONG | in | Anzahl der zu lesenden Bytes. Kurze Reads sind bei EOF oder Pipes normal. |
| ByteOffset | PLARGE_INTEGER | in | Optionaler Datei-Offset. NULL nutzt den aktuellen Dateizeiger (synchrone Datei). |
| Key | PULONG | in | Optionaler Lock-Key. Außerhalb von Byte-Range-Locking nahezu immer NULL. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x6 | win10-1507 |
| Win10 1607 | 0x6 | win10-1607 |
| Win10 1703 | 0x6 | win10-1703 |
| Win10 1709 | 0x6 | win10-1709 |
| Win10 1803 | 0x6 | win10-1803 |
| Win10 1809 | 0x6 | win10-1809 |
| Win10 1903 | 0x6 | win10-1903 |
| Win10 1909 | 0x6 | win10-1909 |
| Win10 2004 | 0x6 | win10-2004 |
| Win10 20H2 | 0x6 | win10-20h2 |
| Win10 21H1 | 0x6 | win10-21h1 |
| Win10 21H2 | 0x6 | win10-21h2 |
| Win10 22H2 | 0x6 | win10-22h2 |
| Win11 21H2 | 0x6 | win11-21h2 |
| Win11 22H2 | 0x6 | win11-22h2 |
| Win11 23H2 | 0x6 | win11-23h2 |
| Win11 24H2 | 0x6 | win11-24h2 |
| Server 2016 | 0x6 | winserver-2016 |
| Server 2019 | 0x6 | winserver-2019 |
| Server 2022 | 0x6 | winserver-2022 |
| Server 2025 | 0x6 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 06 00 00 00 mov eax, 0x6 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
NtReadFile folgt der klassischen NT-9-Argument-Form (Event/APC-Paar, IO_STATUS_BLOCK, Byte-Offset, Lock-Key), die NtWriteFile, NtDeviceIoControlFile und NtFsControlFile übernehmen — wer einen aufruft, ruft alle vier. SSN `0x6` ist seit Windows 7 fixiert, weil der Call ganz unten in der Tabelle sitzt. Wichtigstes Detail auf Caller-Seite: Bei einer Datei, die *ohne* FILE_SYNCHRONOUS_IO_NONALERT geöffnet wurde, muss ein gültiger ByteOffset oder ein Event-Handle plus Wait übergeben werden — der User-Mode-`ReadFile` versteckt dies, indem es synchron emuliert, wenn weder FILE_FLAG_OVERLAPPED noch OVERLAPPED gegeben sind.
Häufige Malware-Nutzung
Drei wesentliche Offensiv-Muster. (1) **Token-Diebstahl / LSASS-Lesen**: Handle auf eine Section öffnen, die LSASS-Speicher unterlegt, oder auf einen Minidump auf Platte, dann mit NtReadFile Credential-Material ziehen, ohne MiniDumpWriteDump oder NtReadVirtualMemory anzufassen. (2) **Config-/Clipboard-Exfil**: `\Device\KsecDD`, `\??\C:\Users\<u>\AppData\Roaming\Mozilla\Firefox\Profiles\*\logins.json`, Browser-Cookie-SQLite, Outlook PST/OST öffnen und blockweise lesen. (3) **Eigene Backing-Datei eines reflektiven Loaders** rückeinlesen, um Stage 2 von Disk zu staged ohne die OS-Heuristik, die NtMapViewOfSection auf Image-Sektionen markiert. Mit NtCreateFile auf NT-Pfaden (`\??\GLOBALROOT\Device\...`) umgeht der Read Minifilter, die an DOS-Pfaden hängen.
Erkennungsmöglichkeiten
NtReadFile ist für sich genommen nie auffällig — Milliarden Aufrufe pro Host und Tag. Das Signal liegt in (a) *welche Datei*, (b) *wer hat sie geöffnet*, (c) die IRP-Kette. ETW Microsoft-Windows-Kernel-File (`{EDD08927-9CC4-4E65-B970-C2560FB5C289}`) emittiert Read-Events mit Offset und Länge. EDR-Minifilter-Callbacks (IRP_MJ_READ pre/post) sehen jede Leseoperation unabhängig vom User-Mode-Hook, also verbergen direkte Syscalls nichts. Hochwertige Hunts: jeder Nicht-MsMpEng/SearchProtocolHost-Prozess, der `*\Mozilla\*\logins.json`, `*\Chromium\User Data\*\Login Data`, `*\Microsoft\Credentials\*`, `*\Microsoft\Protect\*` (DPAPI-Masterkeys) oder `\Device\HarddiskVolumeShadowCopy*` (NTDS.dit-Extraktion über VSC) liest.
Direkte Syscall-Beispiele
cRead browser logins file synchronously
// Assumes hFile was opened with FILE_SYNCHRONOUS_IO_NONALERT and FILE_READ_DATA.
IO_STATUS_BLOCK iosb = {0};
BYTE buffer[0x4000];
LARGE_INTEGER off = {0}; // start of file
NTSTATUS s = NtReadFile(
hFile,
NULL, // Event
NULL, NULL, // APC routine + context
&iosb,
buffer,
sizeof(buffer),
&off,
NULL); // Key
if (NT_SUCCESS(s)) {
SIZE_T got = iosb.Information;
// got bytes copied into buffer
}asmDirect stub (SSN 0x6) — stack args 5..9
; NtReadFile has 9 args. RCX,RDX,R8,R9 hold the first four; the rest
; sit on the stack after 32-byte home space — caller is responsible.
NtReadFile PROC
mov r10, rcx
mov eax, 06h
syscall
ret
NtReadFile ENDPrustAsync read with event wait
// Cargo: ntapi = "0.4", winapi = { version = "0.3", features = ["synchapi", "ntdef"] }
use ntapi::ntioapi::{NtReadFile, IO_STATUS_BLOCK};
use winapi::um::synchapi::WaitForSingleObject;
use winapi::shared::ntdef::{HANDLE, LARGE_INTEGER};
pub unsafe fn read_async(h_file: HANDLE, h_event: HANDLE, buf: &mut [u8], off: i64) -> i32 {
let mut iosb: IO_STATUS_BLOCK = core::mem::zeroed();
let mut li: LARGE_INTEGER = core::mem::zeroed();
*li.QuadPart_mut() = off;
let s = NtReadFile(
h_file, h_event,
None, core::ptr::null_mut(),
&mut iosb,
buf.as_mut_ptr() as *mut _,
buf.len() as u32,
&mut li,
core::ptr::null_mut(),
);
if s == 0x103 /* STATUS_PENDING */ {
WaitForSingleObject(h_event, u32::MAX);
}
s
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20