NtOpenFile
Ouvre un handle vers un fichier ou un device existant — pendant léger sans création de NtCreateFile.
Prototype
NTSTATUS NtOpenFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | PHANDLE | out | Reçoit le handle vers le fichier ou device ouvert en cas de succès. |
| DesiredAccess | ACCESS_MASK | in | Droits d'accès demandés (FILE_READ_DATA, FILE_GENERIC_READ, SYNCHRONIZE, READ_CONTROL, etc.). |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Chemin namespace NT, ex. \??\C:\Windows\System32\config\SAM ou \Device\HarddiskVolume1\... |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Reçoit le NTSTATUS final et le champ Information (FILE_OPENED ici, vs FILE_CREATED pour NtCreateFile). |
| ShareAccess | ULONG | in | Masque FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE accordé aux ouvertures concurrentes. |
| OpenOptions | ULONG | in | FILE_SYNCHRONOUS_IO_NONALERT, FILE_NON_DIRECTORY_FILE, FILE_OPEN_REPARSE_POINT, FILE_OPEN_FOR_BACKUP_INTENT, etc. |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | 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 |
Module noyau
APIs liées
Stub du syscall
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
Notes non documentées
NtOpenFile est fonctionnellement équivalent à `NtCreateFile` avec `CreateDisposition = FILE_OPEN` mais avec moins d'arguments — pas de taille d'allocation, pas d'attributs étendus, pas d'attributs fichier. Il ne peut pas créer de fichiers. Le SSN `0x33` est stable depuis Windows 10 1507. Le wrapper Win32 `CreateFileW` dispatche toujours vers `NtCreateFile` ; le code user-mode qui préfère NtOpenFile contourne délibérément le chemin de création pour éviter les hooks EDR centrés sur NtCreateFile, ou pour garder une signature d'appel petite pour des stubs en syscall direct.
Usage courant par les malwares
Les cas d'usage se concentrent autour de l'**énumération et lecture furtives du filesystem**. Coupler NtOpenFile à NtQueryDirectoryFile et NtReadFile permet à un loader de parcourir les répertoires et d'avaler des fichiers de config / cibles entièrement via la surface Nt*, esquivant les hooks `kernel32!CreateFileW` et `FindFirstFileW` que les EDR user-mode inlinent fréquemment. `FILE_OPEN_FOR_BACKUP_INTENT` combiné à SeBackupPrivilege permet aussi à l'appel de contourner les DACL en lecture — utile pour les chaînes de staging de ruches (ouvrir directement `\??\C:\Windows\System32\config\SAM` quand on est SYSTEM, sans passer par VSS). NtOpenFile est aussi préféré pour ouvrir des objets device (`\Device\PhysicalDrive0`, `\??\PIPE\...`) dans les outils qui veulent explicitement le chemin NT.
Opportunités de détection
NtOpenFile est bien trop courant pour alerter directement — chaque processus en fait beaucoup. Le signal discriminant est le *chemin cible* combiné à l'*ouvreur* : un processus non système ouvrant `\Device\PhysicalDrive*`, `\??\C:\Windows\System32\config\SAM`, `\??\C:\Windows\NTDS\ntds.dit`, ou tout chemin lié à LSASS est malveillant à forte confiance. Sysmon Event 11 couvre les *créations* de fichiers mais pas les ouvertures pures ; pour les ouvertures, les providers ETW Microsoft-Windows-Kernel-File et Microsoft-Windows-Threat-Intelligence sont la télémétrie primaire, aux côtés des callbacks mini-filter EDR au niveau IRP_MJ_CREATE.
Exemples de syscalls directs
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 }
}Mappings MITRE ATT&CK
Last verified: 2026-05-20