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¶
$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.
CopyOfEntryInUsekennzeichnet 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
AllocatedSizeundRealSizegeben den Stand der letzten Aktualisierung des Eintrags wieder und können veraltet sein. FileEntry(oderParentEntry) 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 i30liest 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¶
- Beginnen Sie mit den Namen im Slack, die laut Zusammenfassung keine Kopien sind, und filtern Sie anschließend mit
--slack-only --no-copies. - Schlagen Sie den
FileEntryin der$MFTnach. DieselbeFileSequencebedeutet dieselbe Datei; eine höhere bedeutet, dass der Datensatz seitdem freigegeben und möglicherweise wiederverwendet wurde. - Durchsuchen Sie das USN-Journal nach dem Namen, um zu erfahren, wann er gelöscht oder umbenannt wurde.
- Vergleichen Sie
$FILE_NAME-Zeitstempel mit den$STANDARD_INFORMATION-Zeitstempeln der$MFT, um Timestomping zu erkennen. - Korrelieren Sie mit Prefetch, LNK, Jump Lists und Ereignisprotokollen, um zu ermitteln, wie die Datei verwendet wurde.
Weitere Informationen¶
- Microsoft: Master File Table
- libfsntfs: Dokumentation des NTFS-Formats
- dfir_ntfs
- INDXRipper
- ys-ntfs-parser (Modul
i30seines Cratesmft)