> Windows Syscalls
ntoskrnl.exeT1083T1005T1106

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

NameTypeDirDescription
FileHandlePHANDLEoutReçoit le handle vers le fichier ou device ouvert en cas de succès.
DesiredAccessACCESS_MASKinDroits d'accès demandés (FILE_READ_DATA, FILE_GENERIC_READ, SYNCHRONIZE, READ_CONTROL, etc.).
ObjectAttributesPOBJECT_ATTRIBUTESinChemin namespace NT, ex. \??\C:\Windows\System32\config\SAM ou \Device\HarddiskVolume1\...
IoStatusBlockPIO_STATUS_BLOCKoutReçoit le NTSTATUS final et le champ Information (FILE_OPENED ici, vs FILE_CREATED pour NtCreateFile).
ShareAccessULONGinMasque FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE accordé aux ouvertures concurrentes.
OpenOptionsULONGinFILE_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 WindowsID de syscallBuild
Win10 15070x33win10-1507
Win10 16070x33win10-1607
Win10 17030x33win10-1703
Win10 17090x33win10-1709
Win10 18030x33win10-1803
Win10 18090x33win10-1809
Win10 19030x33win10-1903
Win10 19090x33win10-1909
Win10 20040x33win10-2004
Win10 20H20x33win10-20h2
Win10 21H10x33win10-21h1
Win10 21H20x33win10-21h2
Win10 22H20x33win10-22h2
Win11 21H20x33win11-21h2
Win11 22H20x33win11-22h2
Win11 23H20x33win11-23h2
Win11 24H20x33win11-24h2
Server 20160x33winserver-2016
Server 20190x33winserver-2019
Server 20220x33winserver-2022
Server 20250x33winserver-2025

Module noyau

ntoskrnl.exeNtOpenFile

APIs liées

CreateFileWNtCreateFileNtReadFileNtQueryDirectoryFileNtClose

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 ENDP

cStealthy 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