Dateisysteme · Lektion 4 von 8
NTFS-Metadatendateien: $LogFile, $UsnJrnl und alternative Datenströme
10 Min. Lesezeit
Lektion 1.3 hat gezeigt, wie die $MFT jede Datei in ihrem aktuellen Zustand beschreibt. Diese Lektion behandelt drei NTFS-Funktionen, die frühere Vorgänge aufzeichnen oder Daten enthalten, die bei einer oberflächlichen Betrachtung übersehen werden: das Transaktionsprotokoll $LogFile, das USN-Änderungsjournal und alternative Datenströme. Damit kann ein Prüfer nachweisen, dass eine Datei erstellt, umbenannt oder gelöscht wurde, auch wenn sie nicht mehr vorhanden ist, und Daten finden, die neben einer gewöhnlichen Datei verborgen sind.
$LogFile: das Transaktionsprotokoll
$LogFile ist MFT-Datensatz 2. NTFS ist ein Journaling-Dateisystem: Bevor es seine eigenen Metadaten (MFT-Datensätze, Verzeichnisindizes, die Belegungsbitmap) ändert, schreibt es einen Protokolldatensatz, der die Änderung beschreibt. Wenn das System währenddessen abstürzt, führt Windows diese Datensätze beim nächsten Einbinden erneut aus oder macht sie rückgängig, damit die Metadaten konsistent bleiben. $LogFile schützt nur Metadaten; es bewahrt keine Kopien von Dateiinhalten auf, die in nichtresidente $DATA-Attribute geschrieben wurden.
Struktur
- Neustartbereich. Die ersten beiden 4.096-Byte-Seiten tragen die Signatur
RSTR. Sie sind zwei Kopien des Neustartbereichs, der die aktuelle Protokollposition und den Ausgangspunkt der Wiederherstellung festhält. - Protokolldatensatzseiten. Der Rest der Datei besteht aus Seiten mit der Signatur
RCRD. Jeder Protokolldatensatz enthält eine Protokollsequenznummer (LSN), eine Transaktions-ID, eine _Redo_-Operation (wie die Änderung anzuwenden ist) und eine _Undo_-Operation (wie sie rückgängig zu machen ist) sowie die betroffenen Bytes. Zu den Operationsnamen gehörenInitializeFileRecordSegment,DeallocateFileRecordSegment,AddIndexEntryAllocation,DeleteIndexEntryAllocationundUpdateResidentValue. - Verknüpfung mit der $MFT. Jeder MFT-Datensatzheader enthält am Offset 0x08 die LSN der letzten protokollierten Änderung an diesem Datensatz. Dadurch können Werkzeuge Protokolldatensätze den MFT-Datensätzen zuordnen.
Das Protokoll ist als Ringpuffer organisiert und wird ständig wiederverwendet. Standardmäßig beträgt seine Größe einige zehn MB; lesen Sie die tatsächliche Größe aus dem $DATA-Attribut von MFT-Datensatz 2 aus, statt sie anzunehmen. Auf einem stark genutzten Systemdatenträger deckt dieser Speicherplatz nur Minuten bis wenige Stunden an Aktivitäten ab; auf einem wenig genutzten Volume kann er weiter zurückreichen.
Was es aufdecken kann
Da Redo- und Undo-Daten die tatsächlichen Metadatenbytes enthalten, kann $LogFile kürzlich erfolgte Dateierstellungen, Umbenennungen und Löschungen zeigen, einschließlich alter und neuer Namen, aus einem Verzeichnis entfernter Indexeinträge sowie residenter Daten oder $STANDARD_INFORMATION-Werte vor und nach einer Änderung (nützlich, wenn Zeitstempel verändert wurden). Protokolldatensätze haben kein eigenes Zeitfeld: Zeitangaben stammen aus den Zeitstempeln innerhalb der protokollierten Attributdaten oder aus der Korrelation mit dem USN-Journal. Beispiele für Parser sind LogFileParser und NTFS Log Tracker; letzterer korreliert $LogFile mit $UsnJrnl.
Das USN-Änderungsjournal
Das Journal der Update Sequence Number (USN) protokolliert Änderungen an Dateien und Verzeichnissen, damit Sicherungs- und Indexierungssoftware ermitteln kann, was sich geändert hat. Windows aktiviert es standardmäßig auf dem Systemvolume. Es befindet sich in $Extend\$UsnJrnl (die MFT-Datensatznummer von $UsnJrnl ist im Gegensatz zu $LogFile nicht festgelegt) und hat zwei benannte $DATA-Datenströme:
| Datenstrom | Inhalt |
|---|---|
$J | Die Änderungsdatensätze, die nacheinander angehängt werden |
$Max | Journaleinstellungen: maximale Größe, Zuweisungsdelta und Journal-ID |
Die USN eines Datensatzes ist sein Byte-Offset innerhalb von $J. Wenn das Journal seine maximale Größe überschreitet, gibt NTFS die Speicherzuweisung für den ältesten Teil von $J frei und macht ihn zu einem _Sparse_-Bereich (einem Bereich ohne zugeordnete Cluster, der beim Lesen Nullen liefert). Die logische Größe von $J kann daher mehrere GB betragen, während nur die jüngsten einigen zehn MB Datensätze enthalten. fsutil usn queryjournal C: zeigt auf einem laufenden System die konfigurierten Werte an; auf Systemvolumes von Windows 10 und 11 beträgt das Maximum üblicherweise 32 MB.
Wie weit das Journal zurückreicht, hängt von der Aktivität und der maximalen Größe ab: auf einer Workstation oft Tage bis Wochen, auf einem stark genutzten Server manchmal nur Stunden. Ältere Datensätze können in nicht zugeordnetem Speicherplatz und Volumenschattenkopien erhalten bleiben. Auf NTFS-Wechseldatenträgern fehlt das Journal häufig, sofern es nicht durch Software oder fsutil usn createjournal aktiviert wurde; FAT32 und exFAT (Lektion 1.5) haben überhaupt kein Journal.
USN_RECORD_V2
Die meisten Datensätze auf NTFS verwenden Version 2 (Version 3 verwendet 128-Bit-Datei-IDs und tritt hauptsächlich auf ReFS auf). Alle Ganzzahlen liegen im Little-Endian-Format vor.
| Offset | Größe | Feld |
|---|---|---|
| 0x00 | 4 | Datensatzlänge (Vielfaches von 8) |
| 0x04 | 2 + 2 | Hauptversion (2), Nebenversion (0) |
| 0x08 | 8 | Dateireferenznummer (6-Byte-MFT-Eintrag + 2-Byte-Sequenznummer) |
| 0x10 | 8 | Dateireferenznummer des übergeordneten Verzeichnisses |
| 0x18 | 8 | USN |
| 0x20 | 8 | Zeitstempel (FILETIME, UTC, Zeitpunkt, zu dem der Datensatz geschrieben wurde) |
| 0x28 | 4 | Änderungsgrund-Flags |
| 0x2C | 4 | Quelleninformation (ungleich null bei Änderungen durch Systemdienste wie die Replikation) |
| 0x30 | 4 | Sicherheits-ID |
| 0x34 | 4 | Dateiattribute (z. B. 0x20 Archiv, 0x10 Verzeichnis) |
| 0x38 | 2 + 2 | Dateinamenlänge in Bytes, Dateinamen-Offset (normalerweise 0x3C) |
| 0x3C | var. | Dateiname, UTF-16LE, ohne Pfad |
Häufige Änderungsgrund-Flags:
| Flag | Wert | Bedeutung |
|---|---|---|
| DATA_OVERWRITE | 0x00000001 | Daten im unbenannten Datenstrom wurden überschrieben |
| DATA_EXTEND | 0x00000002 | Der unbenannte Datenstrom wurde vergrößert |
| DATA_TRUNCATION | 0x00000004 | Der unbenannte Datenstrom wurde verkleinert |
| FILE_CREATE | 0x00000100 | Datei oder Verzeichnis erstellt |
| FILE_DELETE | 0x00000200 | Datei oder Verzeichnis gelöscht |
| RENAME_OLD_NAME | 0x00001000 | Der Datensatz enthält den Namen vor einer Umbenennung oder Verschiebung |
| RENAME_NEW_NAME | 0x00002000 | Der Datensatz enthält den Namen nach einer Umbenennung oder Verschiebung |
| BASIC_INFO_CHANGE | 0x00008000 | Attribute oder Zeitstempel geändert |
| STREAM_CHANGE | 0x00200000 | Ein benannter Datenstrom wurde hinzugefügt, entfernt oder umbenannt |
| CLOSE | 0x80000000 | Letztes Handle geschlossen; beendet diese Gruppe von Änderungen |
Wie aus einem Vorgang mehrere Datensätze werden
Änderungsgrund-Flags sammeln sich an. Solange eine Datei geöffnet ist, wird für jede neue Art von Änderung ein Datensatz geschrieben, dessen Änderungsgrund die ODER-Verknüpfung aller bisher aufgetretenen Änderungsgründe ist. Wenn das letzte Handle geschlossen wird, schreibt NTFS einen abschließenden Datensatz mit zusätzlich gesetztem CLOSE. Das Erstellen und Beschreiben einer Datei ergibt also FILE_CREATE, dann FILE_CREATE | DATA_EXTEND, dann FILE_CREATE | DATA_EXTEND | CLOSE. Lesen Sie den CLOSE-Datensatz als Zusammenfassung des gesamten Vorgangs.
Zwei Hinweise sind zu beachten. „Löschen“ im Explorer verschiebt die Datei normalerweise nach $Recycle.Bin. Dies erscheint als RENAME_OLD_NAME- / RENAME_NEW_NAME-Datensätze (der neue Name beginnt mit $R), nicht als FILE_DELETE; FILE_DELETE erscheint beim endgültigen Löschen, beim Leeren des Papierkorbs oder beim programmgesteuerten Löschen. Außerdem belegt ein Datensatz, dass eine Änderung stattgefunden hat, nicht jedoch, wer sie vorgenommen hat oder warum.
Vollständige Pfade rekonstruieren
Ein Datensatz enthält nur den Dateinamen und die Dateireferenznummer des übergeordneten Verzeichnisses. Um den Pfad zu rekonstruieren, zerlegen Sie die Referenz des übergeordneten Verzeichnisses in MFT-Eintrag (niederwertige 6 Bytes) und Sequenznummer (höherwertige 2 Bytes), suchen Sie diesen Eintrag in der $MFT, übernehmen Sie seinen Namen und wiederholen Sie den Vorgang mit seinem übergeordneten Verzeichnis, bis Sie Eintrag 5, das Stammverzeichnis, erreichen. Wenn die Sequenznummer in der $MFT von der im Datensatz abweicht, wurde der Eintrag freigegeben oder wiederverwendet, und der Pfad ist nicht verlässlich. Die $MFT zeigt aktuelle Ordnernamen; Umbenennungsdatensätze eines Ordners zeigen frühere Namen. MFTECmd beispielsweise parst $J in CSV und löst eine Spalte ParentPath auf, wenn die $MFT mit -m übergeben wird.
Alternative Datenströme
Jede NTFS-Datei hat ein unbenanntes $DATA-Attribut (Typ 0x80, Namenslänge 0): den Inhalt, den Sie beim Öffnen der Datei sehen. Eine Datei oder ein Verzeichnis kann außerdem beliebig viele benannte $DATA-Attribute haben, die als alternative Datenströme (ADS) bezeichnet werden. Jeder davon ist ein separates $DATA-Attribut im selben MFT-Datensatz, dessen Datenstromname im Attributheader gespeichert ist; ein kleiner Datenstrom ist resident innerhalb des Datensatzes gespeichert, ein größerer hat eigene Clusterfolgen. Die Syntax lautet file.txt:stream oder vollständig file.txt:stream:$DATA. Die im Explorer angezeigte Größe ist nur die des unbenannten Datenstroms.
Zone.Identifier
Wenn ein Browser oder E-Mail-Client unter Windows eine Datei aus dem Internet speichert, fügt er einen Datenstrom namens Zone.Identifier mit Text wie [ZoneTransfer], ZoneId=3, ReferrerUrl=… und HostUrl=… hinzu. ZoneId 3 ist die Internetzone (0 lokaler Computer, 1 lokales Intranet, 2 vertrauenswürdige Sites, 4 eingeschränkte Sites). Neuere Chromium-basierte Browser wie Chrome und Edge unter Windows 10 und 11 fügen die Felder ReferrerUrl und HostUrl hinzu; HostUrl ist die Download-URL. Andere Programme schreiben möglicherweise nur die ZoneId-Zeile. Dies ist ein direkter Herkunftsnachweis, doch einige Download-Werkzeuge und Programme zum Entpacken von Archiven erstellen ihn nicht oder geben ihn nicht weiter.
Daten verbergen und verlieren
In einen Datenstrom können beliebige Inhalte geschrieben werden, beispielsweise mit type secret.zip > notes.txt:x.zip, und die sichtbare Datei ändert ihre Größe nicht; Schadsoftware hat auf diese Weise Nutzlasten gespeichert. ADS existieren nur auf NTFS (und ReFS): Beim Kopieren einer Datei auf FAT32 oder exFAT, beim Anhängen an eine E-Mail oder beim Hochladen gehen sämtliche benannten Datenströme verloren. Ihr Fehlen auf Wechselmedien beweist daher nichts über das Original.
Datenströme erkennen
dir /rlistet Datenströme alsnotes.txt:x.zip:$DATAauf.- PowerShell
Get-Item .\notes.txt -Stream *listet jeden Datenstrom und seine Länge auf. - Bei einem Datenträgerabbild kennzeichnet die MFTECmd-Ausgabe Dateien mit Datenströmen (
HasAds) und gibt jeden Datenstrom in einer eigenen Zeile aus (IsAds), mit residentem Zone.Identifier-Text inZoneIdContents. Das Hinzufügen eines Datenstroms erzeugt außerdem USN-Datensätze mit STREAM_CHANGE.
Durchgerechnetes Beispiel: eine Datei im USN-Journal
$J eines Windows-11-Systemdatenträgers enthält diese Datensätze (dazwischenliegende Datensätze anderer Dateien wurden ausgelassen, weshalb die USNs Sprünge aufweisen). Alle haben die Dateireferenz 0x0005000000012A3F und die Referenz des übergeordneten Verzeichnisses 0x0003000000009C40.
| USN | Zeitstempel (UTC) | Änderungsgrund | Name |
|---|---|---|---|
| 1476395008 | 2026-03-14T09:21:07.250Z | FILE_CREATE (0x00000100) | draft.txt |
| 1476395088 | 2026-03-14T09:21:07.251Z | FILE_CREATE, DATA_EXTEND (0x00000102) | draft.txt |
| 1476395168 | 2026-03-14T09:21:07.253Z | FILE_CREATE, DATA_EXTEND, CLOSE (0x80000102) | draft.txt |
| 1476421632 | 2026-03-14T09:24:51.008Z | RENAME_OLD_NAME (0x00001000) | draft.txt |
| 1476421712 | 2026-03-14T09:24:51.008Z | RENAME_NEW_NAME (0x00002000) | keys.txt |
| 1476421792 | 2026-03-14T09:24:51.009Z | RENAME_NEW_NAME, CLOSE (0x80002000) | keys.txt |
| 1476444584 | 2026-03-14T09:30:12.115Z | FILE_DELETE, CLOSE (0x80000200) | keys.txt |
Datensatzlänge. draft.txt besteht aus 9 Zeichen, 18 Bytes in UTF-16: 60 + 18 = 78, auf ein Vielfaches von 8 aufgerundet = 80 Bytes. Deshalb liegt der nächste Datensatz derselben Folge bei 1476395008 + 80 = 1476395088. keys.txt ergibt 60 + 16 = 76, aufgefüllt auf 80.
Zeitstempel. Der erste Datensatz enthält den FILETIME-Wert 134179536672500000 (100-ns-Intervalle seit 1601-01-01). 134179536672500000 / 10.000.000 = 13.417.953.667,25 s; minus 11.644.473.600 s (1601 bis 1970) = Unix-Zeit 1.773.480.067,25 = 2026-03-14T09:21:07.250Z.
Referenzen. 0x0005000000012A3F: niederwertige 6 Bytes 0x12A3F = MFT-Eintrag 76.351, höherwertige 2 Bytes = Sequenznummer 5. Das übergeordnete Verzeichnis 0x0003000000009C40 ist Eintrag 40.000, Sequenznummer 3. In der $MFT ist Eintrag 40.000 (Sequenznummer 3) Desktop, dessen Kette übergeordneter Verzeichnisse aus ana, Users und dem Stammverzeichnis besteht. Der vollständige Pfad lautete somit C:\Users\ana\Desktop\draft.txt; die Datei wurde am selben Speicherort in keys.txt umbenannt.
Interpretation. Die Datei wurde um 09:21:07Z erstellt und beschrieben, um 09:24:51Z umbenannt und um 09:30:12Z endgültig gelöscht, nicht in den Papierkorb verschoben, da keine Umbenennung nach $Recycle.Bin erscheint. Eintrag 76.351 enthält möglicherweise bereits eine andere Datei mit Sequenznummer 6; das Journal belegt dennoch den alten Namen und die Zeitangaben. $LogFile kann die Löschung bestätigen, sofern es 09:30 noch abdeckt.
Prüfungsschwerpunkt: Rechnen Sie damit, eine Zeitangabe, einen ursprünglichen Namen oder einen vollständigen Pfad aus $J angeben zu müssen. Dazu müssen Sie den CLOSE-Datensatz einer Datensatzfolge lesen, RENAME_OLD_NAME von RENAME_NEW_NAME unterscheiden und die Referenz des übergeordneten Verzeichnisses über die $MFT auflösen. Sie könnten gefragt werden, woher eine heruntergeladene Datei stammt (HostUrl in Zone.Identifier) oder welche Datei einen verborgenen Datenstrom enthält. Sie sollten wissen, welches Artefakt welches Zeitfenster abdeckt: $LogFile Minuten bis Stunden, $J üblicherweise Tage bis Wochen.
Kernpunkte
- $LogFile (MFT-Datensatz 2) protokolliert Metadatentransaktionen als Redo-/Undo-Datensätze hinter einem
RSTR-Neustartbereich; es ist klein, als Ringpuffer organisiert und deckt nur jüngste Aktivitäten ab. $Extend\$UsnJrnl:$Jenthält USN_RECORD_V2-Einträge; die USN ist der Offset des Datensatzes im Sparse-Datenstrom$J, und$Maxenthält die Größeneinstellungen.- Änderungsgrund-Flags sammeln sich bis zu einem Datensatz mit CLOSE an; Umbenennungen erzeugen einen OLD_NAME- und einen NEW_NAME-Datensatz; das Löschen im Explorer ist üblicherweise eine Umbenennung nach
$Recycle.Bin. - Pfade werden anhand der Dateireferenz des übergeordneten Verzeichnisses über die $MFT rekonstruiert; prüfen Sie die Sequenznummer, bevor Sie dem Ergebnis vertrauen.
- Benannte $DATA-Attribute sind alternative Datenströme; Zone.Identifier zeichnet ZoneId, ReferrerUrl und HostUrl auf, und auf FAT32/exFAT gehen alle Datenströme verloren.