Kurze Antwort: Verwenden Sie analyzeMFT für reines Python-Parsing, wenn Sie es installieren können, libmft, wenn Sie ein typisiertes Objektmodell wollen, oder rufen Sie omerbenamram/mft auf, wenn es auf Geschwindigkeit ankommt. Pures Python-Parsing ist ~10–50× langsamer als das Rust-Crate, reicht aber für einmalige Skripte.
Was Sie lesen
Die NTFS-Master File Table ist eine Folge von Einträgen fester Größe von 1.024 Byte. Um sie aus Python zu parsen, müssen Sie nur:
- Die
$MFT-Datei öffnen (oder aus einem Disk-Image lesen). - Sie in Schritten von 1.024 Byte durchgehen.
- Das Fixup-Array auf jeden Eintrag anwenden. Siehe Anatomie eines Eintrags für das byteweise Layout.
- Den Attributstrom innerhalb jedes Eintrags durchlaufen.
Die unten genannten Bibliotheken erledigen alle vier Schritte. Die meisten Analysten greifen nur dann auf rohes struct.unpack zurück, wenn eine Bibliothek ein benötigtes Feld nicht offenlegt.
Option 1: analyzeMFT
analyzeMFT ist der klassische reine-Python-MFT-Parser, ursprünglich von David Kovar und nach wie vor gepflegt. CLI-orientiert, aber importierbar.
# pip install analyzeMFT
from analyzeMFT.mft_analyzer import MFTAnalyzer
analyzer = MFTAnalyzer(mft_file="path/to/$MFT", output_file="out.csv")
analyzer.analyze()
Die erzeugte CSV hat eine Zeile pro Eintrag mit Zeitstempeln sowohl aus $STANDARD_INFORMATION als auch aus $FILE_NAME. Gut genug für tabellenbasierte Triage.
Wann einsetzen: kleine $MFT-Dateien, Ad-hoc-Skripte, keine nativen Abhängigkeiten erlaubt.
Grenzen: langsam bei mehreren Gigabyte Eingabe (single-threaded pures Python), und das Objektmodell ist eher auf CSV-Ausgabe ausgelegt als auf programmatische Durchläufe.
Option 2: libmft (typisiertes Objektmodell)
Wenn Sie Einträge als Python-Objekte abfragen wollen, stellt libmft ein typisiertes Modell bereit, das nah an der On-Disk-Struktur liegt.
# pip install libmft
from libmft.api import MFT
with open("path/to/$MFT", "rb") as f:
mft = MFT(f)
for entry in mft:
if not entry.is_deleted():
continue
name = entry.get_full_path()
si = entry.get_attributes(0x10)[0] # $STANDARD_INFORMATION
print(name, si.created, si.modified)
libmft löst Eltern-Referenzen auf, sodass Sie jeden Eintrag nach seinem vollständigen Pfad fragen können, ohne den Durchlauf selbst zu schreiben. Es verarbeitet auch $ATTRIBUTE_LIST-Extension-Records transparent — etwas, das die CSV-Schicht von analyzeMFT vor Ihnen verbirgt.
Wann einsetzen: Sie wollen Logik schreiben, die Einträge durchläuft, nach Attributen filtert und eine eigene Form ausgibt.
Option 3: Aufruf eines Rust-Parsers
Wenn die $MFT groß ist (~1 GB+) oder Sie über viele Datenträger batchen, ist die praktisch schnellste Option, aus Python heraus einen nativen Parser aufzurufen und dessen JSON zu lesen.
import json
import subprocess
# omerbenamram/mft — `cargo install mft` oder Release-Binary herunterladen
proc = subprocess.run(
["mft_dump", "-o", "json", "path/to/$MFT"],
capture_output=True, check=True,
)
for line in proc.stdout.splitlines():
record = json.loads(line)
if record["header"]["flags"] & 0x1 == 0: # IN_USE gelöscht → entfernt
print(record["entry"], record["file_name"]["name"])
mft_dump gibt JSON Lines aus — ein Eintrag pro Zeile —, das sich sauber in Python streamen lässt, ohne die gesamte Ausgabe in den Speicher zu laden. Im Vergleich zu analyzeMFT mit derselben Eingabe ist der Rust-Parser typischerweise 10–50× schneller und verbraucht ein Zehntel des Speichers.
Wann einsetzen: Produktions-Pipelines, große Eingaben, oder überall dort, wo Parse-Zeit zählt.
$MFT direkt aus einem Disk-Image lesen
Wenn Sie ein rohes .dd- oder .E01-Image statt einer extrahierten $MFT-Datei haben, nutzen Sie pytsk3 (Python-Bindings für The Sleuth Kit), um auf dem Volume zu $MFT zu navigieren und deren Bytes zu streamen:
import pytsk3
img = pytsk3.Img_Info("disk.dd")
fs = pytsk3.FS_Info(img, offset=0) # verwenden Sie den Offset der NTFS-Partition
mft_file = fs.open_meta(inode=0) # $MFT ist immer Inode 0
size = mft_file.info.meta.size
data = mft_file.read_random(0, size)
# data enthält jetzt $MFT; an libmft übergeben oder auf Platte schreiben
Das ist der sauberste Ansatz, wenn das Volume auf Partitionsebene verschlüsselt, aber über einen Entschlüsseler gemountet ist, der Ihnen ein rohes Image liefert.
Häufige Stolperfallen
- Das Fixup-Array vergessen. Wenn Sie rohe 1.024-Byte-Blöcke ohne USA-Anwendung lesen, erhalten Sie an den Offsets 510 und 1022 jedes Eintrags Müll. Jede der oben genannten Bibliotheken erledigt das für Sie — schreiben Sie nur dann einen eigenen Parser, wenn Sie den Fixup-Mechanismus verstehen (siehe Anatomie eines Eintrags).
- Die Eintragsnummer als Identität behandeln. Eintragsnummern werden wiederverwendet. Die 64-Bit-File Reference (Eintragsnummer plus Sequenznummer) ist die Kennung, die nicht kollidiert.
- Die beiden Zeitstempelsätze verwechseln. Jeder Eintrag trägt Zeitstempel sowohl in
$STANDARD_INFORMATION(häufig aktualisiert) als auch in$FILE_NAME(meist stabil). Für die Erkennung von Timestomping brauchen Sie beide — siehe die vier MFT-Zeitstempel.
Wann man Python ganz überspringt
Für eine einmalige interaktive Analyse ohne Installation legen Sie die $MFT einfach auf den Browser-Parser dieser Seite. Er führt dasselbe Crate omerbenamram/mft als WebAssembly aus, filtert und sucht clientseitig und exportiert CSV — kein Python erforderlich.