NtLockFile
Acquiert un verrou sur une plage d'octets d'un fichier ouvert, optionnellement exclusif et optionnellement asynchrone.
Prototype
NTSTATUS NtLockFile( HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER ByteOffset, PLARGE_INTEGER Length, ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | HANDLE | in | Handle vers un fichier ouvert avec au moins FILE_READ_DATA ou FILE_WRITE_DATA. |
| Event | HANDLE | in | Événement optionnel signalé à la complétion async. NULL si ApcRoutine ou attente synchrone. |
| ApcRoutine | PIO_APC_ROUTINE | in | Routine APC mode utilisateur optionnelle déclenchée quand le verrou est accordé en async. |
| ApcContext | PVOID | in | Valeur de contexte renvoyée à ApcRoutine. |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Reçoit le NTSTATUS final et Information (toujours 0 pour NtLockFile). |
| ByteOffset | PLARGE_INTEGER | in | Offset de début (en octets) de la plage à verrouiller. |
| Length | PLARGE_INTEGER | in | Longueur en octets de la plage à verrouiller. 0x7FFFFFFFFFFFFFFF couvre essentiellement tout le fichier. |
| Key | ULONG | in | Cookie corrélant ce verrou avec un futur NtUnlockFile / NtLockFile portant la même clé. |
| FailImmediately | BOOLEAN | in | Si TRUE, renvoie STATUS_LOCK_NOT_GRANTED au lieu d'attendre si la plage est déjà verrouillée. |
| ExclusiveLock | BOOLEAN | in | Si TRUE, demande un verrou exclusif (écriture) ; FALSE demande un verrou partagé (lecture). |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0xF9 | win10-1507 |
| Win10 1607 | 0xFE | win10-1607 |
| Win10 1703 | 0x102 | win10-1703 |
| Win10 1709 | 0x103 | win10-1709 |
| Win10 1803 | 0x104 | win10-1803 |
| Win10 1809 | 0x104 | win10-1809 |
| Win10 1903 | 0x105 | win10-1903 |
| Win10 1909 | 0x105 | win10-1909 |
| Win10 2004 | 0x10A | win10-2004 |
| Win10 20H2 | 0x10A | win10-20h2 |
| Win10 21H1 | 0x10A | win10-21h1 |
| Win10 21H2 | 0x10B | win10-21h2 |
| Win10 22H2 | 0x10B | win10-22h2 |
| Win11 21H2 | 0x111 | win11-21h2 |
| Win11 22H2 | 0x112 | win11-22h2 |
| Win11 23H2 | 0x112 | win11-23h2 |
| Win11 24H2 | 0x114 | win11-24h2 |
| Server 2016 | 0xFE | winserver-2016 |
| Server 2019 | 0x104 | winserver-2019 |
| Server 2022 | 0x110 | winserver-2022 |
| Server 2025 | 0x114 | winserver-2025 |
Module noyau
APIs liées
Stub du syscall
4C 8B D1 mov r10, rcx B8 14 01 00 00 mov eax, 0x114 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
Les verrous de plage d'octets sont *obligatoires* sous Windows (contrairement aux verrous consultatifs de la plupart des Unix) : un processus tiers qui tente une lecture/écriture chevauchante reçoit STATUS_FILE_LOCK_CONFLICT (ERROR_LOCK_VIOLATION 33) même s'il n'a jamais tenté de verrouiller. Les verrous sont libérés à la fermeture du handle, mais un processus tenant un handle ouvert plus un verrou exclusif 0…INT64_MAX interdit effectivement à tout autre processus de lire le contenu. Le paramètre Key permet à un même propriétaire d'empiler de nombreux verrous chevauchants et de les libérer par cookie.
Usage courant par les malwares
Deux abus distincts. (1) **Auto-verrouillage anti-analyse** : l'implant ouvre son propre fichier avec FILE_SHARE_READ retiré, puis pose un verrou exclusif sur toute la plage. Les scanners AV qui tentent de lire le fichier pour le matching de signatures statiques rencontrent ERROR_LOCK_VIOLATION ; nombre de scanners naïfs loggent et passent. Combiné à la propriété de verrouillage à l'exécution des handles FILE_EXECUTE, cela fait échouer la suppression in-place tant que le processus n'a pas quitté. (2) **Manipulation UX rançongiciel** : les chiffreurs posent un verrou exclusif sur la note de rançon pendant la phase de chiffrement pour que la victime ne puisse pas l'écarter ; une fois le chiffrement terminé, le verrou est libéré et la note devient visible/modifiable. Certains wipers verrouillent aussi le fichier de métadonnées équivalent au MFT pour retarder l'outillage de récupération.
Opportunités de détection
NtLockFile est à *gros volume* — chaque document Office, base SQLite, PST Outlook et pack Git l'utilise en permanence. Filtres utiles : des verrous tenus sur des exécutables (.exe/.dll/.scr) par le *même* processus qui a ouvert le fichier sont inhabituels hors débogueurs. ETW Microsoft-Windows-Kernel-FileIO émet FileIo/OperationEnd avec les sous-types Lock/Unlock mais est volumineux. La télémétrie la plus actionnable est le côté *échec* : un pic de réponses ERROR_LOCK_VIOLATION (33) aux scanners légitimes est un indicateur indirect qu'un binaire s'auto-verrouille. Les minifilters EDR peuvent observer IRP_MJ_LOCK_CONTROL directement et corréler avec l'image du processus verrouilleur.
Exemples de syscalls directs
cSelf-lock anti-analysis stub
// Re-open our own image without FILE_SHARE_READ, then take a whole-file
// exclusive lock. AV scanners that try to read it for static signature
// matching hit STATUS_FILE_LOCK_CONFLICT and move on.
HANDLE hSelf = CreateFileW(g_selfPath,
GENERIC_READ, 0 /* no share */, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
IO_STATUS_BLOCK iosb;
LARGE_INTEGER off = { .QuadPart = 0 };
LARGE_INTEGER len = { .QuadPart = 0x7FFFFFFFFFFFFFFFLL };
NtLockFile(hSelf, NULL, NULL, NULL, &iosb,
&off, &len, 0,
TRUE, // FailImmediately
TRUE); // ExclusiveLockasmx64 direct stub (Win11 24H2 SSN 0x114)
NtLockFile PROC
mov r10, rcx
mov eax, 114h
syscall
ret
NtLockFile ENDPrustRansom-note lock during encryption
// Cargo: ntapi = "0.4", windows-sys = "0.59"
// Hold an exclusive lock on the note while we burn through the file tree.
unsafe {
let off: i64 = 0;
let len: i64 = i64::MAX;
let mut iosb = zeroed();
let st = NtLockFile(h_note,
null_mut(), None, null_mut(),
&mut iosb,
&off as *const _ as _, &len as *const _ as _,
0,
1, // FailImmediately
1); // ExclusiveLock
assert!(st == 0);
}
// ...encrypt files...
unsafe { NtUnlockFile(h_note, &mut iosb, &off as *const _ as _, &len as *const _ as _, 0); }Mappings MITRE ATT&CK
Last verified: 2026-05-20