NtLockFile
Adquiere un bloqueo de rango de bytes sobre un archivo abierto, opcionalmente exclusivo y opcionalmente asíncrono.
Prototipo
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 );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| FileHandle | HANDLE | in | Handle a un archivo abierto con al menos FILE_READ_DATA o FILE_WRITE_DATA. |
| Event | HANDLE | in | Evento opcional señalado al completarse async. NULL si se usa ApcRoutine o espera síncrona. |
| ApcRoutine | PIO_APC_ROUTINE | in | Rutina APC de modo usuario opcional disparada cuando el bloqueo se concede async. |
| ApcContext | PVOID | in | Valor de contexto devuelto a ApcRoutine. |
| IoStatusBlock | PIO_STATUS_BLOCK | out | Recibe el NTSTATUS final e Information (siempre 0 para NtLockFile). |
| ByteOffset | PLARGE_INTEGER | in | Desplazamiento inicial en bytes del rango a bloquear. |
| Length | PLARGE_INTEGER | in | Longitud en bytes del rango a bloquear. 0x7FFFFFFFFFFFFFFF cubre prácticamente todo el archivo. |
| Key | ULONG | in | Cookie que correlaciona este bloqueo con un futuro NtUnlockFile / NtLockFile con la misma clave. |
| FailImmediately | BOOLEAN | in | Si TRUE, devuelve STATUS_LOCK_NOT_GRANTED en lugar de esperar si el rango ya está bloqueado. |
| ExclusiveLock | BOOLEAN | in | Si TRUE, solicita un bloqueo exclusivo (escritura); FALSE pide un bloqueo compartido (lectura). |
IDs de syscalls por versión de Windows
| Versión 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 |
Módulo del kernel
APIs relacionadas
Stub del 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
Notas no documentadas
Los bloqueos de rango de bytes son *obligatorios* en Windows (a diferencia de los avisorios de la mayoría de los Unix): un proceso ajeno que intenta una lectura/escritura solapada recibe STATUS_FILE_LOCK_CONFLICT (ERROR_LOCK_VIOLATION 33) aunque nunca haya intentado bloquear. Los bloqueos se liberan al cerrar el handle, pero un proceso que mantiene un handle abierto más un bloqueo exclusivo 0…INT64_MAX impide efectivamente que cualquier otro proceso lea el contenido. El parámetro Key permite a un mismo propietario apilar muchos bloqueos solapados y liberarlos por cookie.
Uso común por malware
Dos abusos distintos. (1) **Auto-bloqueo anti-análisis**: el implante abre su propio fichero con FILE_SHARE_READ removido y luego toma un bloqueo exclusivo sobre todo el rango. Los escáneres AV que intentan leer el fichero para coincidencia de firma estática reciben ERROR_LOCK_VIOLATION; muchos escáneres ingenuos lo registran y saltan. Combinado con la propiedad de bloqueo en ejecución de los handles FILE_EXECUTE, esto hace fallar la eliminación in-situ hasta que el proceso termina. (2) **Manipulación de UX de ransomware**: los cifradores toman bloqueos exclusivos sobre el fichero de nota de rescate durante la fase de cifrado para que la víctima no pueda apartarla; una vez completado el cifrado se libera el bloqueo y la nota queda visible/modificable. Algunos wipers también bloquean el fichero de metadatos equivalente a la MFT para retrasar la recuperación.
Oportunidades de detección
NtLockFile es de *alto volumen* — cada documento Office, base SQLite, PST de Outlook y pack de Git lo usa constantemente. Filtros útiles: bloqueos mantenidos sobre ejecutables (.exe/.dll/.scr) por el *mismo* proceso que abrió el fichero son inusuales fuera de depuradores. ETW Microsoft-Windows-Kernel-FileIO emite FileIo/OperationEnd con subtipos Lock/Unlock pero es voluminoso. La telemetría más accionable es el lado del *fallo*: un pico de respuestas ERROR_LOCK_VIOLATION (33) a escáneres legítimos es un indicador indirecto de que algo se está auto-bloqueando. Los minifilters EDR pueden observar IRP_MJ_LOCK_CONTROL directamente y correlacionar con la imagen del proceso bloqueador.
Ejemplos de syscalls directos
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); }Mapeos MITRE ATT&CK
Last verified: 2026-05-20