Master File Table

MFT

Die bemerkenswerteste Quelle wertvoller Informationen für einen Analysten aus dem NTFS-Dateisystem ist die Master File Table (MFT). Der Startsektor der MFT befindet sich im Bootsektor der Festplatte, und jede Datei und jedes Verzeichnis auf dem Datenträger hat einen Eintrag in der MFT. Jeder MFT-Eintrag ist 1024 Byte groß, wodurch die MFT sehr einfach zu parsen ist. Jeder MFT-Eintrag beginnt mit der ASCII-Zeichenkette „FILE“ (bei einem Fehler im Eintrag beginnt er mit „BAAD“) und besteht aus einem oder mehreren (meistens mehr) Attributen, die jeweils ihre eigene Kennung und Struktur haben. Abbildung 4.1 zeigt einen Ausschnitt aus einem MFT-Eintrag.

Abbildung 4.1. Auszug aus einem MFT-Datensatz oder -Eintrag.

Die ersten 42 Bytes jedes MFT-Eintrags bestehen aus einer Header-Struktur mit 12 Elementen, und die restlichen 982 Bytes hängen weitgehend von den Werten im Header und den verschiedenen im Eintrag enthaltenen Attributen ab. Nicht alle Elemente innerhalb der Kopfzeile des MFT-Eintrags sind für einen forensischen Analytiker unmittelbar nützlich; Abbildung 4.2 zeigt jedoch fünf der Elemente, die unmittelbar nützlich sind.

Abbildung 4.2. MFT-Datensatz-Kopfzeilen (in Little-Endian-Reihenfolge).

Wie in Abbildung 4.2 (ein Ausschnitt aus Abbildung 4.1) dargestellt, sehen wir die „FILE“-Signatur am Anfang des Datensatzes. Dann sehen wir die Sequenznummer oder den Wert, der erhöht wird, wenn der Eintrag zugewiesen oder freigegeben wird. Da dieser spezielle MFT-Eintrag der erste Eintrag innerhalb der MFT ist und sich auf die Datei „$MFT“ bezieht, ist die Sequenznummer logischerweise 1. Als nächstes folgt die Link-Anzahl, die sich auf die Anzahl der Verzeichnisse bezieht, die Einträge für diesen Eintrag haben (bei Hardlinks wird dieser Wert erhöht). Als Nächstes folgt der Offset des Datensatzes zum ersten Attribut; wenn Sie sich den Offset 0x38 innerhalb des Datensatzes ansehen, werden Sie feststellen, dass das erste Attribut eine Kennung von 0x10, also 16, hat. Schließlich sehen wir den Flags-Wert, der uns sagt, ob der Eintrag zugewiesen ist (wenn das Bit 0x01 gesetzt ist) und ob der Eintrag ein Verzeichnis ist (wenn das Bit 0x02 gesetzt ist). Kurz gesagt, können wir anhand dieser beiden Werte feststellen, ob der Eintrag zugewiesen oder gelöscht wurde und ob es sich um eine Datei oder ein Verzeichnis handelt. Wenn der Header geparst wird, kann der Pseudocode dafür wie folgt dargestellt werden:

if ($mft{flags} & 0x0001) – allocated; else unallocated/deleted

if ($mft{flags} & 0x0002) – folder/directory; else file

Der in Abbildung 4.2 sichtbare Wert für die Flags ist „0x01“, was eine zugewiesene Datei anzeigt. Ein Wert von 0x00 würde eine gelöschte Datei anzeigen, und ein Wert von 0x03 würde ein zugewiesenes Verzeichnis anzeigen.

Tipp

MFT-Datensätze

MFT-Datensätze werden nicht gelöscht, sobald sie erstellt wurden; neue Datensätze werden der MFT nach Bedarf hinzugefügt, und Datensätze für gelöschte Dateien werden wiederverwendet.

Wie bereits erwähnt, sind nur die ersten 42 Bytes strukturiert; danach besteht der Rest des MFT-Eintrags aus einem oder mehreren Attributfeldern. Es gibt keine formale Spezifikation oder Anweisung, die besagt, dass ein MFT-Eintrag bestimmte Attribute enthalten muss, aber in den meisten MFT-Einträgen können Sie ein Attribut $STANDARD_INFORMATION und ein Attribut $FILE_NAME erwarten. Dieser Abschnitt befasst sich mit diesen beiden Attributen, da sie Zeitstempelinformationen liefern, die für forensische Analysten wertvoll sind. Wir werden auch einen kurzen Blick auf das $DATA-Attribut werfen und die übrigen Attribute als Übung für den interessierten und neugierigen Leser belassen.

Der Kopf jedes Attributs enthält einen 16-Byte-Header, der unter anderem den Typ des Attributs, die Gesamtlänge des Attributs und die Angabe, ob das Attribut im MFT-Eintrag resident ist oder nicht, identifiziert.

Hinweis

MFT-Metadaten-Dateien

Die ersten 16 Einträge der MFT enthalten Informationen über Metadaten-Dateien; sie werden jedoch nicht alle verwendet. Diejenigen, die nicht verwendet werden, werden in einem zugewiesenen Zustand belassen und enthalten nur grundlegende Informationen.

Mit Hilfe dieser Header-Informationen können wir den MFT-Eintrag analysieren und wertvolle Informationen aus jedem Attribut extrahieren. Zum Beispiel existiert das Attribut $STANDARD_INFORMATION (das immer resident ist) für jeden Datei- und Verzeichniseintrag und hat die Kennung 0x10 (d.h. 16). Dieses Attribut enthält die Dateizeiten für den MFT-Eintrag (zumindest drei davon), die wir sehen, wenn wir „dir“ an der Eingabeaufforderung eingeben: die Änderungszeit, die Zeit des letzten Zugriffs und das Erstellungsdatum (Geburtsdatum) der Datei oder des Verzeichnisses, auch als „MAC“-Zeiten bezeichnet. Das Attribut enthält einen vierten Zeitwert, der das letzte Mal angibt, dass der MFT-Eintrag geändert wurde. Insgesamt werden diese Zeiten als „MACE“-Zeiten (mit dem „E“, das sich auf die Änderungszeit des MFT-Eintrags bezieht) oder „MACB“-Zeiten (mit dem „C“, das sich auf die Änderungszeit des MFT-Eintrags bezieht) bezeichnet.

Warnung

Datei-Zeiten

NTFS-Datei-Zeiten werden im Format der koordinierten Weltzeit (UTC) aufgezeichnet, was der Greenwich Mean Time entspricht. Dies gilt für alle Zeiten; in jedem MFT-Eintrag werden einem Dateidatensatz wahrscheinlich mindestens 8 Zeiten zugeordnet, oft sogar 12 oder mehr. Auf dem FAT-Dateisystem werden die Dateizeiten im Format der lokalen Systemzeit verwaltet.

Das Attribut $FILE_NAME (Kennung 0x30 oder 48) findet sich auch bei den meisten Datei- und Verzeichnis-MFT-Einträgen; tatsächlich haben viele MFT-Einträge mehr als ein Attribut $FILE_NAME. Wie das Attribut $STANDARD_INFORMATION ist dieses Attribut immer resident und enthält ebenfalls vier Zeitwerte; allerdings werden diese Zeitwerte normalerweise gesetzt, wenn die Datei auf dem System erstellt wird. Im Gegensatz zu den Dateizeiten im Attribut $STANDARD_INFORMATION werden diese Dateizeiten nicht durch normale Systemaktivitäten oder böswillige Manipulationen beeinflusst und können daher verwendet werden, um Indikatoren für böswillige Aktivitäten zu ermitteln, und es können Schritte unternommen werden, um den Zeitpunkt zu verschleiern, zu dem ein System infiziert wurde. Das folgende Codebeispiel (Funktion parseSIAttr()) zeigt, wie das Attribut $STANDARD_INFORMATION geparst werden kann:

sub parseSIAttr {

my $si = shift;

my %si;

my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)

= unpack(„VVCCvvvVv“,substr($si,0,22));

my $content = substr($si,$ofs_content,$sz_content);

my ($t0,$t1) = unpack(„VV“,substr($Inhalt,0,8));

$si{c_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(„VV“,substr($Inhalt,8,8));

$si{m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(„VV“,substr($content,16,8));

$si{mft_m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(„VV“,substr($inhalts,24,8));

$si{a_time} = getTime($t0,$t1);

$si{flags} = unpack(„V“,substr($inhalts,32,4));

return %si;

}

Tipp

GetTime

Die getTime()-Funktion, die im Code-Listing für das soeben angegebene parseSIAttr()-Attribut zu sehen ist, besteht aus einem von Andreas Schuster entliehenen Code, der die 64-Bit-Zeitstempel des FILETIME-Objekts in eine 32-Bit-Unix-Zeit übersetzt, die dann über die in Perl eingebaute gmtime()-Funktion in eine für Menschen lesbare Zeit umgewandelt werden kann. Dieser Code sieht wie folgt aus:

sub getTime($$) {

my $lo = shift;

my $hi = shift;

my $t;

if ($lo == 0 && $hi == 0) {

$t = 0;

} else {

$lo -= 0xd53e8000;

$hi -= 0x019db1de;

$t = int($hi*429.4967296 + $lo/1e7);

};

$t = 0 if ($t < 0);

return $t;

}

Dieser Code ist sehr nützlich für das Parsen und Übersetzen eines beliebigen FILETIME-Objekts, unabhängig davon, woher es entnommen wurde.

Auf einem normalen System können viele MFT-Einträge zwei $FILE_NAME-Attribute haben: eines für den vollständigen Namen der Datei (oder des Verzeichnisses) und eines für den DOS-8.3-Dateinamen. Wenn eine Datei zum Beispiel „myreallylongfile.txt“ heißt, wird der 8.3-Dateiname als „myreal~1.txt“ angezeigt. Dies dient der Kompatibilität mit älteren Dateisystemen und solchen, die keine langen Dateinamen unterstützen. Es ist also nicht ungewöhnlich, dass auf einem normalen Windows-System eine Reihe von MFT-Einträgen mit zwei $FILE_NAME-Attributen mit nahezu identischem Inhalt vorhanden sind. Das folgende Code-Beispiel (Funktion parseFNAttr()) zeigt, wie ein $FILE_NAME-Attribut aus einem MFT-Eintrag geparst und die verfügbaren Daten extrahiert werden können:

sub parseFNAttr {

my $fn = shift;

my %fn;

my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)

= unpack(„VVCCvvvVv“,substr($fn,0,22));

my $content = substr($fn,$ofs_content,$sz_content);

$fn{parent_ref} = unpack(„V“,substr($content,0,4));

$fn{parent_seq} = unpack(„v“,substr($content,6,2));

my ($t0,$t1) = unpack(„VV“,substr($Inhalt,8,8));

$fn{c_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(„VV“,substr($Inhalt,16,8));

$fn{m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(„VV“,substr($Inhalt,24,8));

$fn{mft_m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(„VV“,substr($Inhalt,32,8));

$fn{a_time} = getTime($t0,$t1);

$fn{flags} = unpack(„V“,substr($content,56,4));

$fn{len_name} = unpack(„C“,substr($content,64,1));

$fn{namespace} = unpack(„C“,substr($inhalt,65,1));

$fn{len_name} = $fn{len_name} * 2 if ($fn{namespace} > 0);

$fn{name} = substr($content,66,$fn{len_name});

$fn{name} = cleanStr($fn{name}) if ($fn{namespace} > 0);

$fn{name} =~ s/\x0c/\x2e/g;

$fn{name} =~ s///g;

return %fn;

}

Das letzte Attribut, das wir besprechen, ist das $DATA-Attribut (Kennung 0x80, oder 128). Dieses Attribut enthält oder verweist auf den eigentlichen Inhalt der Datei. Wenn das Flag „nicht resident“ in der Kopfzeile des Attributs nicht gesetzt ist, befindet sich der Inhalt der Datei im $DATA-Attribut des MFT-Eintrags, nach der Kopfzeile und zwei weiteren Strukturen. Dies gilt z. B. für kurze Textdateien oder andere Dateien mit weniger als 700 Byte. Wenn die Daten nicht resident sind, müssen die „Datenläufe“ oder die Orte, an denen sich die Daten auf der Festplatte befinden, übersetzt werden.

Beispielcode für das Parsen von Datenläufen des $DATA-Attributs ist sehr komplex und wird hier nicht vorgestellt. Ebenso ist der Code zum Extrahieren von Informationen aus residenten $DATA-Attributen trivial und besteht aus dem Parsen einiger zusätzlicher Informationen (Größe des Inhalts und Offset zum Inhalt) nach dem Attribut-Header.

Es gibt einige Open-Source-Tools zum Parsen der MFT (insbesondere der Attribute $STANDARD_INFORMATION und $FILE_NAME) und zur Bereitstellung von Zeitstempeldaten für den Analytiker. Eines davon ist das Python-Skript analyzemft.py von David Kovar, zu finden im Internet unter http://www.integriography.com/projects/analyzeMFT. Ein weiteres ist das Perl-Skript mft.pl, aus dem die Funktionen parseSIAttr() und parseFNAttr() extrahiert wurden und das im WinForensicAnalysis-Google-Code-Projekt unter http://code.google.com/p/winforensicaanalysis zur Verfügung steht.

Brian Carriers „The SleuthKit“ (TSK)-Tools sind wahrscheinlich die bekanntesten Werkzeuge zum Sammeln eines breiten Spektrums von Dateisystem- und Dateisystem-Metadaten-Informationen aus erworbenen Images und sogar Live-Systemen. Um beispielsweise eine Auflistung der Dateisystem $STANDARD_INFORMATION-Attributdateizeiten von einem erworbenen Image zu sammeln, kann ein Analyst einen Befehl ähnlich dem folgenden verwenden:

C:\tsk>fls -f ntfs -m C:/ -p -r G:\case\xp.img > G:\case\files\bodyfile.txt

Dieser Befehl erzeugt ein sogenanntes „bodyfile“, ein Zwischendateiformat, in dem diese Informationen gespeichert werden, bevor sie in eine Zeitleiste der Dateisystemaktivitäten umgewandelt werden. In manchen Fällen muss der Analyst den Schalter „-o“ hinzufügen, um den Offset zu der Partition zu identifizieren, die auf dem Live-System als Laufwerk „C:\“ angezeigt wurde; diese Offset-Information kann manuell mit einem Hex-Editor oder mit mmls.exe ermittelt werden.

Ein Analyst kann dieselben Informationen auch von einem Live-Remote-System mit F-Response sammeln. Wenn der Analyst eine ordnungsgemäße Verbindung zu dem entfernten System hergestellt und das Laufwerk C:\ auf seinem eigenen System als F:\ gemountet hat, kann er einen Befehl ähnlich dem folgenden verwenden, um die Dateizeiten des Attributs $STANDARD_INFORMATION für die Dateien auf der Partition C:\ zu erfassen:

C:\tsk>fls -f ntfs -m C:/ -p -r \\.\F: > g:\case\files\bodyfile.txt

Der vollständige Satz von TSK-Tools, zusammen mit Dokumentation und Nutzungsinformationen, kann im Internet auf der SleuthKit-Website gefunden werden, http://www.sleuthkit.org.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.