NtQueryVolumeInformationFile
Récupère les propriétés filesystem et volume (label, taille, type de périphérique, attributs) du volume associé à un handle de fichier.
Prototype
NTSTATUS NtQueryVolumeInformationFile( HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | HANDLE | in | Handle vers un fichier ou répertoire du volume cible ; FILE_READ_ATTRIBUTES suffit. |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Reçoit le statut de complétion et le nombre d'octets écrits dans FsInformation. |
| FsInformation | PVOID | out | Buffer fourni par l'appelant recevant la structure d'info volume correspondant à FsInformationClass. |
| Length | ULONG | in | Taille en octets du buffer FsInformation. |
| FsInformationClass | FS_INFORMATION_CLASS | in | Classe à récupérer : FileFsVolumeInformation=1, Label=2, Size=3, Device=4, Attribute=5, etc. |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x49 | win10-1507 |
| Win10 1607 | 0x49 | win10-1607 |
| Win10 1703 | 0x49 | win10-1703 |
| Win10 1709 | 0x49 | win10-1709 |
| Win10 1803 | 0x49 | win10-1803 |
| Win10 1809 | 0x49 | win10-1809 |
| Win10 1903 | 0x49 | win10-1903 |
| Win10 1909 | 0x49 | win10-1909 |
| Win10 2004 | 0x49 | win10-2004 |
| Win10 20H2 | 0x49 | win10-20h2 |
| Win10 21H1 | 0x49 | win10-21h1 |
| Win10 21H2 | 0x49 | win10-21h2 |
| Win10 22H2 | 0x49 | win10-22h2 |
| Win11 21H2 | 0x49 | win11-21h2 |
| Win11 22H2 | 0x49 | win11-22h2 |
| Win11 23H2 | 0x49 | win11-23h2 |
| Win11 24H2 | 0x49 | win11-24h2 |
| Server 2016 | 0x49 | winserver-2016 |
| Server 2019 | 0x49 | winserver-2019 |
| Server 2022 | 0x49 | winserver-2022 |
| Server 2025 | 0x49 | winserver-2025 |
Module noyau
APIs liées
Stub du syscall
4C 8B D1 mov r10, rcx B8 49 00 00 00 mov eax, 0x49 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
Sous-tend toute la famille Win32 `GetVolumeInformationW` / `GetDiskFreeSpaceExW` / `GetDriveTypeW`. Le noyau route l'IRP via `IopXxxControlFile` → `IRP_MJ_QUERY_VOLUME_INFORMATION` vers le driver filesystem monté sur le device object sous-jacent à `FileHandle` (NTFS, FAT32, exFAT, ReFS, redirecteurs réseau). La SSN `0x49` est l'un des numéros les plus stables de toute la table NT — inchangé de Windows 10 1507 à Win11 24H2 et Server 2025 — car `Query` et `Set` volume info sont verrouillés ABI depuis NT 3.51. Les cinq classes les plus utilisées sont : `FileFsVolumeInformation` (label + serial + date de création), `FileFsLabelInformation` (jumeau write-only), `FileFsSizeInformation` (secteurs/clusters/libres), `FileFsDeviceInformation` (`FILE_DEVICE_DISK` vs `FILE_DEVICE_CD_ROM` vs `FILE_DEVICE_NETWORK_FILE_SYSTEM`), et `FileFsAttributeInformation` (nom du filesystem + flags comme `FILE_READ_ONLY_VOLUME`).
Usage courant par les malwares
**C'est l'un des syscalls les plus utilisés dans les ransomwares modernes.** LockBit (toutes générations 1.0 → 4.0 / Black), BlackCat / ALPHV, Royal, Conti, Hive, Akira et BlackSuit parcourent tous les lettres de lecteur `A:` à `Z:`, ouvrent chaque racine, et émettent `NtQueryVolumeInformationFile(FileFsDeviceInformation)` pour connaître le type de périphérique — c'est ainsi qu'ils décident que `D:` est un USB amovible (chiffrer en priorité et utiliser une note de rançon différente), `Z:` est `FILE_DEVICE_NETWORK_FILE_SYSTEM` (chiffrer via SMB — fort impact, propagation latérale rapide), et `X:` est un CD-ROM (ignorer). Ils tirent aussi `FileFsAttributeInformation` pour détecter `FILE_READ_ONLY_VOLUME` et ignorer les médias de récupération / boot Windows qui ne feraient que gaspiller de l'IO et déclencher SmartScreen. Certaines familles (fuite Conti) fingerprint en plus `FileFsVolumeInformation::SerialNumber` pour dédupliquer les montages logiques pointant vers le même volume physique — évitant un double chiffrement d'un LUN iSCSI.
Opportunités de détection
Sysmon n'a pas d'événement pour ça ; c'est un syscall Tier-1 utilisé par Explorer, Defender, les API de backup et essentiellement toute UI de stockage. La détection doit regarder des *patterns* : un seul processus émettant `NtQueryVolumeInformationFile(FileFsDeviceInformation)` sur plus de ~5 handles de racine distincts en quelques secondes, surtout suivi d'énumérations `NtOpenFile` de ces racines, est la signature canonique de drive-discovery ransomware. Microsoft Defender for Endpoint détecte via le schéma `BehaviorEntities` : un seul PID touchant des handles racine marqués `FsRtl` à travers plusieurs valeurs `DeviceType` en 60 s score fort sur la règle `Ransomware:Behavior:DriveEnumeration`. Le provider ETW `Microsoft-Windows-Kernel-File` événement 12/14 avec `IrpFlags & IRP_MJ_QUERY_VOLUME_INFORMATION` donne une visibilité kernel sans dépendre des hooks user-mode (que le ransomware contourne par syscall direct).
Exemples de syscalls directs
asmx64 direct stub
; Direct syscall stub for NtQueryVolumeInformationFile (SSN 0x49 across all builds)
NtQueryVolumeInformationFile PROC
mov r10, rcx ; syscall convention
mov eax, 49h ; SSN — historically stable, but resolve dynamically anyway
syscall
ret
NtQueryVolumeInformationFile ENDPcRansomware-style drive enumeration (FileFsDeviceInformation)
// Classic LockBit/Conti pattern: probe A: through Z:, classify by DeviceType,
// pick encryption order accordingly. FILE_READ_ATTRIBUTES is enough access.
typedef struct _FILE_FS_DEVICE_INFORMATION {
ULONG DeviceType; // FILE_DEVICE_DISK=0x07, _CD_ROM=0x02, _NETWORK_FILE_SYSTEM=0x14
ULONG Characteristics; // FILE_REMOVABLE_MEDIA=0x01, FILE_READ_ONLY_DEVICE=0x02, ...
} FILE_FS_DEVICE_INFORMATION;
for (WCHAR d = L'A'; d <= L'Z'; ++d) {
WCHAR path[] = L"\\??\\X:\\"; path[4] = d;
UNICODE_STRING us; RtlInitUnicodeString(&us, path);
OBJECT_ATTRIBUTES oa; InitializeObjectAttributes(&oa, &us, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE h; IO_STATUS_BLOCK iosb;
if (!NT_SUCCESS(NtOpenFile(&h, FILE_READ_ATTRIBUTES, &oa, &iosb,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_DIRECTORY_FILE))) continue;
FILE_FS_DEVICE_INFORMATION info = { 0 };
NtQueryVolumeInformationFile(h, &iosb, &info, sizeof(info),
4 /* FileFsDeviceInformation */);
// info.DeviceType / info.Characteristics now drive encryption strategy.
NtClose(h);
}rustFileFsAttributeInformation — skip read-only volumes
// Cargo: ntapi = "0.4", winapi = { version = "0.3", features = ["ntstatus", "winnt"] }
use ntapi::ntioapi::{NtQueryVolumeInformationFile, IO_STATUS_BLOCK, FileFsAttributeInformation};
use std::mem::MaybeUninit;
#[repr(C)]
struct FileFsAttributeInfo {
file_system_attributes: u32, // FILE_READ_ONLY_VOLUME = 0x00080000
maximum_component_name_length: i32,
file_system_name_length: u32,
file_system_name: [u16; 32],
}
unsafe fn is_read_only(h: *mut core::ffi::c_void) -> bool {
let mut iosb: MaybeUninit<IO_STATUS_BLOCK> = MaybeUninit::uninit();
let mut info: MaybeUninit<FileFsAttributeInfo> = MaybeUninit::uninit();
let st = NtQueryVolumeInformationFile(
h, iosb.as_mut_ptr(), info.as_mut_ptr().cast(),
core::mem::size_of::<FileFsAttributeInfo>() as u32,
FileFsAttributeInformation,
);
st >= 0 && (info.assume_init().file_system_attributes & 0x0008_0000) != 0
}Mappings MITRE ATT&CK
Last verified: 2026-05-20