Skip to content

$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.

Publicado el 8 min de lectura

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:

DesplazamientoTamañoCampo
0x004Firma: RSTR, o CHKD si chkdsk modificó el diario
0x042Desplazamiento del update sequence array
0x062Número de elementos del update sequence array
0x088Último LSN de chkdsk
0x104Tamaño de página del sistema
0x144Tamaño de página del diario
0x182Desplazamiento del área de reinicio
0x1A2Versión menor
0x1C2Versió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:

DesplazamientoTamañoCampoPor qué importa
0x008LSN actualLSN más reciente cuando se escribió esta área de reinicio
0x082Clientes del diarioNúmero de huecos de cliente (normalmente uno: NTFS)
0x0A / 0x0C2 + 2Lista de clientes libres / en uso0xFFFF = vacía
0x0E2Flags0x1 E/S de una sola página (ntfs3); el analizador en el navegador interpreta 0x2 como «desmontado limpiamente»
0x104Bits del número de secuenciaNecesarios para LSN ↔ desplazamiento
0x142Longitud del área de reinicio
0x162Desplazamiento del array de clientesRelativo al área de reinicio
0x188Tamaño del archivo de diarioCompáralo con tu copia: si es más corta, está truncada
0x204Longitud de datos del último LSN
0x242Longitud de la cabecera de registro
0x262Desplazamiento de datos de la página del diarioDónde empiezan los registros dentro de cada página RCRD
0x284Contador de aperturas del diario

El registro de cliente NTFS

Cada hueco de cliente ocupa 0xA0 bytes; NTFS suele ser el único cliente:

DesplazamientoCampoSignificado
0x00LSN más antiguoRegistro más antiguo que la recuperación aún puede necesitar
0x08LSN de reinicio del clienteLSN del último registro de checkpoint
0x1CLongitud del nombre (bytes)
0x20NombreUTF-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:

DesplazamientoCampo
0x00 / 0x04Versión mayor / menor del cliente (0.0 o 1.0)
0x08LSN de inicio del checkpoint
0x10LSN del volcado de la tabla de atributos abiertos
0x18LSN del volcado de nombres de atributos
0x20LSN del volcado de la tabla de páginas sucias
0x28LSN del volcado de la tabla de transacciones
0x30–0x3CLongitudes 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 diariofile_data_bitsseq_bits
256 KiB (la muestra sintética del sitio)1549
64 MiB (un tamaño habitual)2341

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 $MFT guarda, en el desplazamiento 0x08 de 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ónSignificado
LSN más bajo ≈ LSN más altoMuy poco historial (diario redimensionado hace poco o mucha actividad)
La página de reinicio es CHKDchkdsk ha trabajado sobre este diario
LSN actual del área de reinicio > LSN más alto encontradoFalta 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 archivoCopia truncada
«Desmontado limpiamente» en una captura descrita como en vivoRevisa 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

Artículos relacionados

Artículos relacionados