Zum Inhalt

Verzeichnisindizes ($I30)

Was $I30 ist

Jedes NTFS-Verzeichnis führt einen Index der darin enthaltenen Dateien mit dem Namen $I30. Ein kleines Verzeichnis speichert ihn in seinem $MFT-Datensatz ($INDEX_ROOT); ein größeres besitzt zusätzlich INDX-Datensätze, meist je 4.096 Byte, in einem $INDEX_ALLOCATION:$I30-Stream. Jeder Indexeintrag enthält eine Kopie des $FILE_NAME der Datei: ihren Namen, die MFT-Referenz, das übergeordnete Verzeichnis, vier Zeitstempel und zwei Größen, jeweils mit dem Stand der letzten Aktualisierung des Eintrags durch NTFS.

Wird eine Datei gelöscht oder aus einem Verzeichnis heraus umbenannt, entfernt NTFS ihren Eintrag und verschiebt die nachfolgenden Einträge. Die alten Bytes verbleiben im Slack des INDX-Datensatzes, hinter den verwendeten Einträgen, bis spätere Einträge sie überschreiben. Index-Slack kann den Namen, die Zeitstempel und die Größe einer Datei bewahren, deren $MFT-Datensatz wiederverwendet wurde und deren USN-Journal-Datensätze bereits überschrieben wurden.

Bestmögliche Schlussfolgerung: Ein im Index-Slack gefundener Name befand sich zu irgendeinem Zeitpunkt im Index dieses Verzeichnisses, mit den angegebenen $FILE_NAME-Zeitstempeln und -Größen. Ein Slack-Eintrag sagt nicht aus, wann er entfernt wurde oder ob er gelöscht, umbenannt oder durch eine Neuordnung verschoben wurde.

Speicherort und Sicherung

C:\<directory>:$I30:$INDEX_ALLOCATION

$I30 sind NTFS-Metadaten: Sichern Sie sie mit einem forensischen Werkzeug mit Rohzugriff, das den $I30-Stream eines Verzeichnisses exportieren kann (exportierte Dateien heißen oft $I30). Juntei kann außerdem ein Datenträgerabbild oder nicht zugeordneten Speicherplatz nach INDX-Datensätzen durchsuchen. Sichern Sie auch $MFT und $J desselben Volumes, um zu erkennen, was die Slack-Einträge waren.

Hinweise für die Analyse

  • Index-Slack ist unvollständig und ungeordnet. Einträge werden überschrieben, wenn sich das Verzeichnis ändert; ein fehlender Name beweist nichts.
  • Viele Slack-Einträge sind Kopien noch verwendeter Einträge, die beim Verschieben von Einträgen zurückbleiben. CopyOfEntryInUse kennzeichnet sie. Derselbe gelöschte Name kann zudem mehrfach im Slack vorkommen.
  • Die Zeitstempel in einem Indexeintrag sind $FILE_NAME-Zeitstempel mit dem Stand der letzten Aktualisierung des Eintrags. Sie können sowohl von den $STANDARD_INFORMATION- als auch von den $FILE_NAME-Zeitstempeln des $MFT-Datensatzes der Datei abweichen.
  • Auch AllocatedSize und RealSize geben den Stand der letzten Aktualisierung des Eintrags wieder und können veraltet sein.
  • FileEntry (oder ParentEntry) eines Slack-Eintrags kann fehlen, wenn spätere Bytes ihn überschrieben haben. Ist der Wert vorhanden, kann der benannte MFT-Datensatz inzwischen wiederverwendet worden sein: Vergleichen Sie die Sequenznummer.
  • parse-ntfs i30 liest INDX-Datensätze. Der Index eines kleinen Verzeichnisses befindet sich nur in seinem $MFT-Datensatz ($INDEX_ROOT); seine Dateien finden Sie in der $MFT.

Mit Juntei parsen

Usage: juntei parse-ntfs i30 <INPUT> [OPTIONS]

Input:
  -d, --directory <DIR>  Recursively find $I30 files (with $I30 in their name, or starting with an INDX record)
  -f, --file <FILE>      Parse one $I30 stream, or any file holding INDX records (a disk image, unallocated space)

Filtering:
      --slack-only  Only the entries found in slack
      --no-copies   Leave out the slack entries that copy an entry in use

Output:
  -o, --output <FILE>       Save every entry
  -t, --output-type <TYPE>  csv, json, or jsonl
juntei parse-ntfs i30 -f 'Users_$I30'
juntei parse-ntfs i30 -d evidence/ -o i30.csv
juntei parse-ntfs i30 -f 'Users_$I30' --slack-only --no-copies -t jsonl
juntei parse-ntfs i30 -f disk.raw -o carved-i30.csv

Die Zusammenfassung listet die INDX-Datensätze auf (und wie viele davon nur teilweise geschrieben wurden), die verwendeten Einträge und die Einträge im Slack sowie die Namen der Slack-Einträge, die keine exakten Kopien verwendeter Einträge sind. Diese Namen sind Kandidaten für gelöschte oder umbenannte Dateien, für sich genommen aber kein Urteil.

CSV-Ausgabefelder

Feld Interpretation
SourcePath Eingabedatei; unterscheidet Hosts und Verzeichnisse.
RecordOffset, EntryOffset Byte-Offsets des INDX-Datensatzes und des Eintrags in der Eingabe. Unverzichtbar für die Validierung und für Datensätze, die in Datenträgerabbildern gefunden wurden.
RecordVCN, RecordLSN Die Position des Datensatzes im Index-Stream und seine $LogFile-Sequenznummer.
FromSlack True für einen Eintrag, der hinter den verwendeten Einträgen gefunden wurde.
CopyOfEntryInUse Slack-Eintrag mit demselben Namen, Namespace, derselben Datei (sofern bekannt), demselben übergeordneten Verzeichnis und denselben Zeitstempeln wie ein verwendeter Eintrag desselben Verzeichnisindex. In der Regel ein Überbleibsel verschobener Einträge, keine gelöschte Datei.
Filename Der Name im Verzeichnis.
Namespace win32, dos (8.3-Kurzname), win32_and_dos oder posix.
FileEntry, FileSequence Die MFT-Referenz der Datei. Leer bei einem Slack-Eintrag, dessen Header überschrieben wurde.
ParentEntry, ParentSequence Die MFT-Referenz des Verzeichnisses. Leer, wenn andere Bytes sie überschrieben haben.
CreatedUTC, ModifiedUTC, MFT-ModifiedUTC, AccessedUTC $FILE_NAME-Zeitstempel mit einer Genauigkeit von 100 ns, mit dem Stand der letzten Aktualisierung des Eintrags.
AllocatedSize, RealSize Größen, die NTFS in den Eintrag kopiert hat; siehe die Hinweise oben.
FileAttributes Mit | verbundene Attributnamen (hidden|archive); is_directory für ein Unterverzeichnis. Bits, die diese Juntei-Version nicht benennt, bleiben hexadezimal erhalten (0x00800000).
ReparseValue Reparse-Tag oder Größe der erweiterten Attribute aus $FILE_NAME.
Problems Schäden im Datensatz, etwa teilweise geschriebene Sektoren. Einträge aus einem beschädigten Datensatz verdienen dennoch eine sorgfältige Prüfung.

JSON/JSONL enthalten dieselben Felder in snake_case, mit problems als Liste und null für unbekannte Werte.

Wie Slack-Einträge gefunden werden

Der Slack wird an jeder 8-Byte-Grenze, an der Einträge beginnen, nach vollständigen Einträgen durchsucht, nach $FILE_NAME-Attributen, deren Eintrags-Header überschrieben wurde, und am Anfang des Slacks nach einem $FILE_NAME, dessen Referenz auf das übergeordnete Verzeichnis durch das Ende der verwendeten Einträge überschrieben wurde. Ein Kandidat muss so aussehen wie das, was Windows schreibt: ein gültiger UTF-16-Name ohne Steuerzeichen oder Pfadtrennzeichen, vier Zeitstempel zwischen 1980 und 2100, ein bekannter Namespace und bekannte Attribut-Flags. Eine Referenz auf das übergeordnete Verzeichnis jenseits von 32 Bit besteht aus überschriebenen Bytes und bleibt leer.

Das Update-Sequence-Array jedes Datensatzes wird angewendet. Ein Sektor, der nicht mit dem Update-Sequence-Wert endet, wurde nur teilweise geschrieben; Juntei liest den Datensatz so, wie er ist, und nennt die Sektoren in Problems.

Untersuchungsstrategie

  1. Beginnen Sie mit den Namen im Slack, die laut Zusammenfassung keine Kopien sind, und filtern Sie anschließend mit --slack-only --no-copies.
  2. Schlagen Sie den FileEntry in der $MFT nach. Dieselbe FileSequence bedeutet dieselbe Datei; eine höhere bedeutet, dass der Datensatz seitdem freigegeben und möglicherweise wiederverwendet wurde.
  3. Durchsuchen Sie das USN-Journal nach dem Namen, um zu erfahren, wann er gelöscht oder umbenannt wurde.
  4. Vergleichen Sie $FILE_NAME-Zeitstempel mit den $STANDARD_INFORMATION-Zeitstempeln der $MFT, um Timestomping zu erkennen.
  5. Korrelieren Sie mit Prefetch, LNK, Jump Lists und Ereignisprotokollen, um zu ermitteln, wie die Datei verwendet wurde.

Weitere Informationen