NtOpenFile
Abre un handle a un archivo o dispositivo existente — la contraparte ligera sin creación de NtCreateFile.
Prototipo
NTSTATUS NtOpenFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | PHANDLE | out | Recibe el handle al archivo o dispositivo abierto en caso de éxito. |
| DesiredAccess | ACCESS_MASK | in | Derechos de acceso solicitados (FILE_READ_DATA, FILE_GENERIC_READ, SYNCHRONIZE, READ_CONTROL, etc.). |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Ruta de espacio de objetos NT, p. ej. \??\C:\Windows\System32\config\SAM o \Device\HarddiskVolume1\... |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Recibe el NTSTATUS final y el campo Information (FILE_OPENED aquí, vs FILE_CREATED para NtCreateFile). |
| ShareAccess | ULONG | in | Máscara FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE concedida a aperturas 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 por versión de Windows
| Versión 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 |
Módulo del kernel
APIs relacionadas
Stub del 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
Notas no documentadas
NtOpenFile es funcionalmente equivalente a `NtCreateFile` con `CreateDisposition = FILE_OPEN` pero con menos argumentos — sin tamaño de asignación, sin atributos extendidos, sin atributos de archivo. No puede crear archivos. El SSN `0x33` lleva estable desde Windows 10 1507. El wrapper Win32 `CreateFileW` siempre despacha a `NtCreateFile`; el código user mode que prefiere NtOpenFile evita deliberadamente la ruta de creación para evadir hooks EDR centrados en NtCreateFile, o para mantener una firma de llamada pequeña en stubs de syscall directo.
Uso común por malware
Los casos de uso se agrupan en torno a la **enumeración y lectura sigilosas del filesystem**. Combinar NtOpenFile con NtQueryDirectoryFile y NtReadFile permite a un loader recorrer directorios y absorber archivos de configuración / objetivos enteramente vía la superficie Nt*, esquivando los hooks `kernel32!CreateFileW` y `FindFirstFileW` que los EDR de user mode suelen inlinear. `FILE_OPEN_FOR_BACKUP_INTENT` combinado con SeBackupPrivilege también permite que la llamada eluda DACLs en lectura — útil para cadenas de staging de hives (abrir `\??\C:\Windows\System32\config\SAM` directamente como SYSTEM, sin pasar por VSS). NtOpenFile también se prefiere para abrir objetos de dispositivo (`\Device\PhysicalDrive0`, `\??\PIPE\...`) en herramientas que quieren explícitamente la ruta NT.
Oportunidades de detección
NtOpenFile es demasiado común para alertar directamente — cada proceso hace muchas. La señal discriminante es la *ruta destino* combinada con el *abridor*: un proceso no sistema abriendo `\Device\PhysicalDrive*`, `\??\C:\Windows\System32\config\SAM`, `\??\C:\Windows\NTDS\ntds.dit`, o cualquier ruta vinculada a LSASS es maliciosa con alta confianza. Sysmon Event 11 cubre *creaciones* de archivos pero no aperturas puras; para aperturas, los proveedores ETW Microsoft-Windows-Kernel-File y Microsoft-Windows-Threat-Intelligence son la telemetría primaria, junto con callbacks mini-filter de EDR a nivel IRP_MJ_CREATE.
Ejemplos de syscalls directos
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 }
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20