$LogFile: el área de reinicio y los LSN, explicados
En las páginas de reinicio del $LogFile de NTFS: campos del área de reinicio, registro de cliente NTFS, checkpoints y cómo pasar un LSN a un desplazamiento.
TL;DR. Las dos primeras páginas de $LogFile son páginas de reinicio RSTR. Cada una contiene un área de reinicio: el LSN actual, el tamaño del diario, el número de bits de secuencia, flags y un registro de cliente para NTFS que apunta al último checkpoint. Un LSN es un número de 64 bits cuyos bits bajos son el desplazamiento del registro en unidades de 8 bytes y cuyos bits altos son un contador de vueltas; con seq_bits del área de reinicio, desplazamiento = (LSN << seq_bits) >> (seq_bits − 3). Los LSN solo crecen, así que ordenan todo lo que hay en el diario, y esos mismos LSN aparecen en las cabeceras de los registros del $MFT.
Si alguna vez tienes que explicar por qué un analizador dice «LSN 115720 → 117880» o comprobar un registro a mano en un editor hexadecimal, esta es la parte del formato que necesitas. La estructura a nivel de página está en el $LogFile 1.1 frente al 2.0.
La cabecera de la página de reinicio
Hay dos copias: en el desplazamiento 0 y una página de sistema más adelante (normalmente 0x1000). No están necesariamente sincronizadas (dfir.ru); el lector valida ambas y se queda con la que tenga el LSN actual más alto. Desplazamientos según libfsntfs y ntfs3:
| Desplazamiento | Tamaño | Campo |
|---|---|---|
0x00 | 4 | Firma: RSTR, o CHKD si chkdsk modificó el diario |
0x04 | 2 | Desplazamiento del update sequence array |
0x06 | 2 | Número de elementos del update sequence array |
0x08 | 8 | Último LSN de chkdsk |
0x10 | 4 | Tamaño de página del sistema |
0x14 | 4 | Tamaño de página del diario |
0x18 | 2 | Desplazamiento del área de reinicio |
0x1A | 2 | Versión menor |
0x1C | 2 | Versión mayor (1 o 2 en la práctica) |
Aplica las correcciones (fix-ups) del update sequence array antes de leer nada más allá del primer sector.
El área de reinicio
En el desplazamiento indicado en 0x18:
| Desplazamiento | Tamaño | Campo | Por qué importa |
|---|---|---|---|
0x00 | 8 | LSN actual | LSN más reciente cuando se escribió esta área de reinicio |
0x08 | 2 | Clientes del diario | Número de huecos de cliente (normalmente uno: NTFS) |
0x0A / 0x0C | 2 + 2 | Lista de clientes libres / en uso | 0xFFFF = vacía |
0x0E | 2 | Flags | 0x1 E/S de una sola página (ntfs3); el analizador en el navegador interpreta 0x2 como «desmontado limpiamente» |
0x10 | 4 | Bits del número de secuencia | Necesarios para LSN ↔ desplazamiento |
0x14 | 2 | Longitud del área de reinicio | |
0x16 | 2 | Desplazamiento del array de clientes | Relativo al área de reinicio |
0x18 | 8 | Tamaño del archivo de diario | Compáralo con tu copia: si es más corta, está truncada |
0x20 | 4 | Longitud de datos del último LSN | |
0x24 | 2 | Longitud de la cabecera de registro | |
0x26 | 2 | Desplazamiento de datos de la página del diario | Dónde empiezan los registros dentro de cada página RCRD |
0x28 | 4 | Contador de aperturas del diario |
El registro de cliente NTFS
Cada hueco de cliente ocupa 0xA0 bytes; NTFS suele ser el único cliente:
| Desplazamiento | Campo | Significado |
|---|---|---|
0x00 | LSN más antiguo | Registro más antiguo que la recuperación aún puede necesitar |
0x08 | LSN de reinicio del cliente | LSN del último registro de checkpoint |
0x1C | Longitud del nombre (bytes) | |
0x20 | Nombre | UTF-16: NTFS |
Checkpoints: registro de tipo 2
El LSN de reinicio del cliente apunta a un registro del diario de tipo 2 (reinicio de cliente). Para NTFS, su contenido (NTFS_RESTART en ntfs3) enumera los LSN y longitudes de los volcados de tablas escritos en ese checkpoint:
| Desplazamiento | Campo |
|---|---|
0x00 / 0x04 | Versión mayor / menor del cliente (0.0 o 1.0) |
0x08 | LSN de inicio del checkpoint |
0x10 | LSN del volcado de la tabla de atributos abiertos |
0x18 | LSN del volcado de nombres de atributos |
0x20 | LSN del volcado de la tabla de páginas sucias |
0x28 | LSN del volcado de la tabla de transacciones |
0x30–0x3C | Longitudes de los cuatro volcados |
La recuperación arranca desde aquí: recarga la tabla de atributos abiertos y compañía, y luego avanza por el diario. Para el analista, el checkpoint explica por qué aparecen con regularidad registros OpenAttributeTableDump y AttributeNamesDump, y por qué un analizador los necesita para identificar el atributo al que apunta un registro.
Anatomía de un LSN
Un LSN tiene 64 bits divididos en dos:
63 (64 - seq_bits) 0
+-------------------------+-----------------------------------+
| sequence number | offset in 8-byte units |
+-------------------------+-----------------------------------+
El número de secuencia crece cada vez que el diario da la vuelta, lo que mantiene los LSN estrictamente crecientes aunque los desplazamientos se repitan. El reparto depende del tamaño del diario. ntfs3 lo calcula como file_data_bits = log2(log_size) − 3 y seq_bits = 64 − file_data_bits:
| Tamaño del diario | file_data_bits | seq_bits |
|---|---|---|
| 256 KiB (la muestra sintética del sitio) | 15 | 49 |
| 64 MiB (un tamaño habitual) | 23 | 41 |
Lee siempre seq_bits del área de reinicio en lugar de calcularlo.
Del LSN al desplazamiento en el archivo
offset = (LSN << seq_bits) >> (seq_bits - 3)
El desplazamiento a la izquierda elimina el número de secuencia; el desplazamiento a la derecha de seq_bits − 3 recoloca el campo de posición y lo multiplica por 8. dfir.ru da un ejemplo resuelto: con 44 bits de secuencia, el LSN 2124332 tiene número de secuencia 2 y un desplazamiento de 27180 unidades de 8 bytes, es decir, el byte 217440.
Un analizador robusto puede usarlo a la inversa. En lugar de recorrer cadenas de páginas, examina cada página RCRD en busca de cabeceras alineadas a 8 bytes cuyo LSN corresponda exactamente a su propio desplazamiento. Esa comprobación descarta bytes aleatorios y sigue funcionando aunque haya páginas intermedias dañadas; así es como el analizador de $LogFile en el navegador encuentra los registros. Los registros que no caben en el resto de una página continúan tras la cabecera de la página siguiente (y dan la vuelta desde el final del archivo hasta el inicio del área circular); una página de continuación más antigua que el registro significa que el resto se sobrescribió, y el registro se marca como incompleto.
Los LSN fuera del $LogFile
- Cada registro FILE del
$MFTguarda, en el desplazamiento0x08de su cabecera, el LSN del último cambio registrado en él, uno de los vínculos de la NTFS TriForce de David Cowen. Si ese LSN está dentro del rango actual del diario, el cambio que produjo el registro FILE actual sigue en el diario. - Los buffers de índice (
INDX) también llevan un LSN en su cabecera.
Comparar el LSN de un registro del $MFT con el LSN más bajo del diario te dice al instante si su último cambio todavía puede encontrarse.
Qué te dicen los números en la práctica
| Observación | Significado |
|---|---|
| LSN más bajo ≈ LSN más alto | Muy poco historial (diario redimensionado hace poco o mucha actividad) |
La página de reinicio es CHKD | chkdsk ha trabajado sobre este diario |
| LSN actual del área de reinicio > LSN más alto encontrado | Falta la página más reciente: revisa las páginas de cola / rápidas, o la copia está desfasada |
| Tamaño del diario en el área de reinicio > tamaño del archivo | Copia truncada |
| «Desmontado limpiamente» en una captura descrita como en vivo | Revisa las notas de adquisición: el archivo puede proceder de una imagen o de una instantánea |
Preguntas frecuentes
¿Qué es un LSN en NTFS?
Un log sequence number es un identificador de 64 bits asignado a cada registro del $LogFile. Sus bits bajos codifican la posición del registro en el archivo en unidades de 8 bytes, y sus bits altos un número de secuencia que crece cada vez que el diario da la vuelta, de modo que los LSN siempre aumentan.
¿Cómo convierto un LSN del $LogFile en un desplazamiento en el archivo?
Lee del área de reinicio el número de bits de secuencia y calcula (LSN << seq_bits) >> (seq_bits - 3). Así conservas los 64 - seq_bits bits bajos y los multiplicas por 8, lo que da el desplazamiento en bytes de la cabecera del registro dentro del archivo.
Lecturas recomendadas
- Kernel de Linux,
fs/ntfs3/fslog.c:RESTART_HDR,RESTART_AREA,CLIENT_REC,NTFS_RESTART,lsn_to_vbo. - Maxim Suhanov, How the $LogFile works?