OBJECTS.DATA: forensische Analyse des WMI-Repositorys
Wie das WMI-CIM-Repository Objekte speichert: Seiten in OBJECTS.DATA, INDEX.BTR-Schlüssel, die drei MAPPING-Dateien, Klassen, Instanzen und Namens-Hashes.
Kurz gesagt. Das WMI-Repository ist eine kleine Datenbank in C:\Windows\System32\wbem\Repository. OBJECTS.DATA enthält Datensätze in Seiten zu 8 KiB, INDEX.BTR ist ein B-Baum aus Textschlüsseln, die aus SHA-256-Hashes von Namen gebildet werden, und die drei MAPPING-Dateien übersetzen logische Seitennummern in physische. Klassendefinitionen beschreiben das Layout; Instanzen enthalten die Werte. Freigegebene Seiten behalten ihre alten Bytes, und genau das macht eine Wiederherstellung möglich.
Das folgende Layout stammt aus der Forschung von FireEye aus dem Jahr 2015 und aus dem Parser python-cim von Willi Ballenthin; die Kodierung innerhalb jedes Datensatzes folgt Microsofts öffentlicher Spezifikation [MS-WMIO]. Microsoft dokumentiert den Repository-Container selbst nicht; die Feldnamen stammen also aus der Forschungs-Community.
Die Dateien
| Datei | Rolle |
|---|---|
OBJECTS.DATA | Datensätze: Klassendefinitionen und Instanzen, Seiten zu 8 KiB |
INDEX.BTR | B-Baum-Index, Seiten zu 8 KiB, Schlüssel verweisen in OBJECTS.DATA |
MAPPING1.MAP, MAPPING2.MAP, MAPPING3.MAP | Zuordnung logischer → physischer Seiten für beide Dateien, drei Generationen |
Unter Windows XP und Server 2003 liegen dieselben Dateien in Repository\FS\, und Namen werden mit MD5 statt SHA-256 gehasht.
Seiten und Inhaltsverzeichnis
Eine Seite von OBJECTS.DATA, in der Datensätze beginnen, startet mit einem Inhaltsverzeichnis: Einträge zu 16 Byte (Datensatz-ID, Offset in der Seite, Größe, Prüfsumme), abgeschlossen durch einen Eintrag aus Nullen. Ein Datensatz, der größer als der Rest seiner Seite ist, setzt sich auf den folgenden logischen Seiten fort, die kein Inhaltsverzeichnis haben.
Der Index spricht von logischen Seiten. Wo eine logische Seite physisch liegt, regelt die aktuelle MAPPING-Datei: Jeder Eintrag gibt die physische Seitennummer einer logischen Seite an, und ein besonderer Wert markiert unbenutzte. Physische Seiten, auf die kein Eintrag verweist, sind frei — und enthalten noch, was zuletzt dort geschrieben wurde.
Der Index: Schlüssel aus Hashes
INDEX.BTR speichert Textschlüssel. Jeder Teil besteht aus einem Präfix plus dem SHA-256 in hexadezimaler Großschreibung des in Großbuchstaben umgewandelten Namens in UTF-16:
NS_<h("ROOT\SUBSCRIPTION")>/CD_<h("COMMANDLINEEVENTCONSUMER")>.268.2079887499.561
NS_<h("ROOT\SUBSCRIPTION")>/CI_<h("__EVENTFILTER")>/IL_<h(key)>.271.2079886610.299
NS_ ist der Namespace, CD_ eine Klassendefinition, CI_ + IL_ eine Instanz einer Klasse. Das Suffix lautet logische Seite . Datensatz-ID . Länge. Zusammen mit der aktuellen Zuordnung genügt das, um jedes Objekt abzurufen — genau das bedeutet „strukturierter Modus“ in WMI Parser.
Da Namen gehasht werden, enthält der Index nie einen lesbaren Namespace- oder Klassennamen. Namespace-Namen stammen aus __NAMESPACE-Instanzen (jeder Namespace listet seine untergeordneten Namespaces), Klassennamen aus den Klassendefinitionen.
Klassendefinitionen und Instanzen
Ein Datensatz einer Klassendefinition enthält den Namen der Oberklasse, eine FILETIME und dann den in [MS-WMIO] beschriebenen Klassenteil: Qualifizierer, eine Eigenschaftentabelle (Name, CIM-Typ, Deklarationsreihenfolge, Offset in der Wertetabelle) und die Klassenstandards. __EventFilter und __FilterToConsumerBinding sind im Namespace __SystemClass definiert, die Standard-Consumer in root\subscription.
Ein Instanzdatensatz beginnt mit:
- dem Hash des Klassennamens als 64 UTF-16-Zeichen (32 unter XP);
- zwei undokumentierten FILETIMEs (python-cim nennt sie
timestamp1undtimestamp2); - dem Instanzteil: eine Tabelle mit 2 Bit pro Eigenschaft, die angibt, ob jeder Wert gesetzt, NULL oder der Klassenstandard ist; eine Wertetabelle fester Größe; Qualifizierer; dann ein Heap, in dem Strings und Arrays liegen.
Strings im Heap werden als Flag-Byte (0 für 8-Bit-Text, 1 für UTF-16) gefolgt von NUL-terminiertem Text gespeichert. Deshalb findet eine einfache Textsuche in OBJECTS.DATA sowohl CommandLineEventConsumer.Name="…" als auch die Befehlszeilen selbst.
Zum Dekodieren einer Instanz wird ihr Klassenlayout benötigt: Die Eigenschaftenliste ergibt sich aus der Klassendefinition und all ihren Vorfahren (CommandLineEventConsumer → __EventConsumer → __IndicationRelated → __SystemClass).
Was das für eine Untersuchung bedeutet
- Aktive Objekte sind diejenigen, die über den Index und die aktuelle Zuordnung erreichbar sind.
- Gelöschte Objekte bleiben in nicht zugeordneten Seiten oder im ungenutzten Ende einer Seite, bis sie überschrieben werden. Ein Scan nach Hashes von Klassennamen findet sie; die MAPPING-Datei zeigt, dass sie nicht mehr referenziert werden. Siehe gelöschte WMI-Persistenz wiederherstellen.
- Alle Dateien müssen vom selben Zeitpunkt stammen. Eine
INDEX.BTR, die neuer als die MAPPING-Datei ist, verweist auf die falschen Seiten. Sichern Sie aus einer Schattenkopie: WMI-Repository forensisch sichern. - Zeitstempel sind schwach. Klassendefinitionen tragen eine FILETIME, Instanzen zwei undokumentierte; keine davon ist ein dokumentiertes Erstellungsdatum.
WMI Parser implementiert beide Wege — die Auswertung des Index und ein vollständiges Carving — und kennzeichnet jedes Objekt danach, wie es gefunden wurde.
FAQ
Was steht in OBJECTS.DATA?
Jede Klassendefinition und jede Klasseninstanz aller WMI-Namespaces, gespeichert als Datensätze in Seiten zu 8 KiB. Event-Filter, Consumer und Bindings sind darin gewöhnliche Instanzen.
Warum gibt es drei MAPPING-Dateien?
Windows hält drei Generationen der Zuordnung logischer zu physischen Seiten vor, um sich von einem fehlgeschlagenen Schreibvorgang erholen zu können. Die Datei mit der höchsten Version ist aktuell; die anderen beschreiben frühere Zustände.
Lässt sich OBJECTS.DATA ohne INDEX.BTR lesen?
Ja. Instanzdatensätze beginnen mit dem Hash ihres Klassennamens und lassen sich daher durch einen Scan der Datei finden. Der Index liefert zusätzlich die Namespaces und unterscheidet aktive von gelöschten Datensätzen.