Skip to content

Restart Area und LSN im $LogFile erklärt

Ein Blick in die Restart-Seiten des NTFS-$LogFile: Felder der Restart Area, Client-Record von NTFS, Checkpoints – und wie aus einer LSN ein Datei-Offset wird.

Veröffentlicht am 7 Min. Lesezeit

TL;DR. Die ersten beiden Seiten des $LogFile sind RSTR-Restart-Seiten. Jede enthält eine Restart Area: die aktuelle LSN, die Loggröße, die Anzahl der Sequenznummer-Bits, Flags und einen Client-Record für NTFS, der auf den jüngsten Checkpoint zeigt. Eine LSN ist eine 64-Bit-Zahl, deren niederwertige Bits den Offset des Eintrags in 8-Byte-Einheiten und deren höherwertige Bits einen Umlaufzähler enthalten; mit seq_bits aus der Restart Area gilt offset = (LSN << seq_bits) >> (seq_bits − 3). LSNs wachsen nur, sie ordnen also alles im Log – und dieselben LSNs stehen auch in den Record-Headern der $MFT.

Wenn Sie jemals erklären müssen, warum ein Parser „LSN 115720 → 117880“ anzeigt, oder einen Logeintrag von Hand im Hex-Editor prüfen wollen, ist das der Teil des Formats, den Sie brauchen. Den Aufbau auf Seitenebene beschreibt $LogFile-Format 1.1 vs. 2.0: was sich mit Windows 8 ändert.

Der Header der Restart-Seite

Zwei Kopien: bei Offset 0 und eine Systemseite später (meist 0x1000). Sie sind nicht zwingend synchron (dfir.ru); ein Parser prüft beide und behält die mit der höheren aktuellen LSN. Offsets gemäß libfsntfs und ntfs3:

OffsetGrößeFeld
0x004Signatur: RSTR, oder CHKD, wenn chkdsk das Log verändert hat
0x042Offset des Update Sequence Array
0x062Anzahl der Update-Sequence-Array-Einträge
0x088Letzte LSN von chkdsk
0x104Systemseitengröße
0x144Log-Seitengröße
0x182Offset der Restart Area
0x1A2Minor-Version
0x1C2Major-Version (in der Praxis 1 oder 2)

Wenden Sie die Update-Sequence-Fix-ups an, bevor Sie irgendetwas jenseits des ersten Sektors lesen.

Die Restart Area

An dem in 0x18 angegebenen Offset:

OffsetGrößeFeldWarum es wichtig ist
0x008Aktuelle LSNNeueste LSN zum Zeitpunkt, als diese Restart Area geschrieben wurde
0x082Log-ClientsAnzahl der Client-Slots (normalerweise einer: NTFS)
0x0A / 0x0C2 + 2Liste freier / belegter Clients0xFFFF = leer
0x0E2Flags0x1 Single-Page-I/O (ntfs3); der Browser-Parser liest 0x2 als „sauber ausgehängt“
0x104Sequenznummer-BitsNötig für LSN ↔ Offset
0x142Länge der Restart Area
0x162Offset des Client-ArraysRelativ zur Restart Area
0x188Größe der LogdateiMit Ihrer Kopie vergleichen: kürzer heißt abgeschnitten
0x204Datenlänge der letzten LSN
0x242Länge des Eintrags-Headers
0x262Daten-Offset der Log-SeiteWo die Einträge in jeder RCRD-Seite beginnen
0x284Open Log Count

Der Client-Record von NTFS

Jeder Client-Slot ist 0xA0 Bytes groß; NTFS ist normalerweise der einzige Client:

OffsetFeldBedeutung
0x00Oldest LSNÄltester Eintrag, den die Wiederherstellung noch brauchen könnte
0x08Client Restart LSNLSN des jüngsten Checkpoint-Eintrags
0x1CNamenslänge (Bytes)
0x20NameUTF-16: NTFS

Checkpoints: Eintragstyp 2

Die Client Restart LSN zeigt auf einen Logeintrag vom Typ 2 (Client-Restart). Für NTFS listet seine Nutzlast (NTFS_RESTART in ntfs3) die LSNs und Längen der Tabellen-Dumps auf, die bei diesem Checkpoint geschrieben wurden:

OffsetFeld
0x00 / 0x04Client-Major- / -Minor-Version (0.0 oder 1.0)
0x08LSN des Checkpoint-Beginns
0x10LSN des Dumps der Open Attribute Table
0x18LSN des Dumps der Attributnamen
0x20LSN des Dumps der Dirty Page Table
0x28LSN des Dumps der Transaktionstabelle
0x30–0x3CLängen der vier Dumps

Hier setzt die Wiederherstellung an: Sie lädt die Open Attribute Table und die übrigen Tabellen neu und liest dann vorwärts. Für die Analyse erklärt der Checkpoint, warum regelmäßig OpenAttributeTableDump- und AttributeNamesDump-Einträge auftauchen und warum ein Parser sie braucht, um das Zielattribut eines Eintrags zu benennen.

Anatomie einer LSN

Eine LSN hat 64 Bit, zweigeteilt:

 63                         (64 - seq_bits)                    0
 +-------------------------+-----------------------------------+
 |     sequence number     |  offset in 8-byte units           |
 +-------------------------+-----------------------------------+

Die Sequenznummer wächst bei jedem Umlauf des Logs; dadurch bleiben LSNs streng monoton steigend, obwohl sich die Offsets wiederholen. Wo geteilt wird, hängt von der Loggröße ab. ntfs3 leitet das als file_data_bits = log2(log_size) − 3 und seq_bits = 64 − file_data_bits her:

Loggrößefile_data_bitsseq_bits
256 KiB (das synthetische Sample dieser Website)1549
64 MiB (eine übliche Größe)2341

Lesen Sie seq_bits immer aus der Restart Area, statt es zu berechnen.

Von der LSN zum Datei-Offset

offset = (LSN << seq_bits) >> (seq_bits - 3)

Die Linksverschiebung entfernt die Sequenznummer; die Rechtsverschiebung um seq_bits − 3 holt das Offset-Feld zurück und multipliziert es mit 8. dfir.ru rechnet ein Beispiel vor: Bei 44 Sequenzbits hat LSN 2124332 die Sequenznummer 2 und einen Offset von 27180 Acht-Byte-Einheiten, also Byte 217440.

Ein robuster Parser kann das auch umgekehrt nutzen. Statt Seitenketten abzulaufen, durchsucht er jede RCRD-Seite nach 8-Byte-ausgerichteten Headern, deren LSN exakt auf ihren eigenen Offset abgebildet wird. Diese Prüfung verwirft zufällige Bytes und funktioniert auch dann noch, wenn dazwischenliegende Seiten beschädigt sind – so findet der Browser-Parser für das $LogFile die Einträge. Einträge, die nicht in den Rest einer Seite passen, setzen sich hinter dem Header der nächsten Seite fort (und laufen vom Dateiende an den Anfang des zirkulären Bereichs um); ist die Folgeseite älter als der Eintrag, wurde der Rest überschrieben, und der Eintrag wird als unvollständig markiert.

LSNs außerhalb des $LogFile

  • Jeder FILE-Record in der $MFT speichert bei Header-Offset 0x08 die LSN der letzten protokollierten Änderung an diesem Record – eines der Bindeglieder in David Cowens NTFS TriForce. Liegt diese LSN im aktuellen Bereich des Logs, steht die Änderung, die den aktuellen FILE-Record hervorgebracht hat, noch im Log.
  • Auch Indexpuffer (INDX) tragen eine LSN in ihrem Header.

Ein Vergleich der LSN eines $MFT-Records mit der niedrigsten LSN des Logs zeigt sofort, ob seine letzte Änderung noch auffindbar ist.

Was die Zahlen in der Praxis verraten

BeobachtungBedeutung
Niedrigste LSN ≈ höchste LSNSehr wenig Historie (Log kürzlich in der Größe geändert oder starke Aktivität)
Restart-Seite ist CHKDchkdsk hat an diesem Log gearbeitet
Aktuelle LSN in der Restart Area > höchste gefundene Eintrags-LSNNeueste Seite fehlt: Tail- / Fast Pages prüfen, oder die Kopie ist veraltet
Loggröße in der Restart Area > DateigrößeAbgeschnittene Kopie
„Sauber ausgehängt“ bei einer angeblichen Live-SicherungSicherungsprotokoll prüfen: Die Datei stammt womöglich aus einem Image oder Snapshot

Häufig gestellte Fragen

Was ist eine LSN in NTFS?

Eine Log Sequence Number ist eine 64-Bit-Kennung, die jeder Logeintrag im $LogFile erhält. Ihre niederwertigen Bits codieren die Position des Eintrags in der Datei in 8-Byte-Einheiten, ihre höherwertigen Bits eine Sequenznummer, die bei jedem Umlauf des Logs wächst. LSNs steigen daher immer an.

Wie rechne ich eine LSN aus dem $LogFile in einen Datei-Offset um?

Lesen Sie die Anzahl der Sequenznummer-Bits aus der Restart Area und berechnen Sie (LSN << seq_bits) >> (seq_bits - 3). Das behält die unteren 64 - seq_bits Bits und multipliziert sie mit 8 – das ergibt den Byte-Offset des Eintrags-Headers in der Datei.

Weiterführende Literatur

Verwandte Artikel

Verwandte Artikel