Das DMP Dateiformat

Microsofts Debugger und der NT-Kernel erzeugen Speicherabbilder in einem proprietären Format. In diesem Beitrag beschreibe ich den Aufbau der DMP Dateien und zeige, wie man eine gegebene physische Adresse im Speicherabbild lokalisiert.

Eine gegebene physische Adresse in einem Speicherabbild zu finden ist einfach - solange es sich um ein Abbild im "dd"-Format handelt. Bei diesem Typ entsprechen sich nämlich physische Adresse und Offset im Abbild. Microsoft hat sich allerdings dafür entschieden, Speicherabbilder in einem proprietären Format zu erzeugen, das auch einige Informationen über den Zustand des untersuchten Systems enthält. Diese Entscheidung ist nachvollziehbar, schließlich wurden Debugger und Abbildformat zur Suche nach Programmfehlern und nicht für Zwecke der digitalen Forensik entwickelt.

Eine DMP Datei beginnt mit einem Header von genau 4096 Bytes, der Größe einer gewöhnlichen Speicherseite. Ich dokumentiere in diesem Artikel nur die wichtigsten Felder des Headers. Wer neugierig ist, kann die vollständigen Deklarationen der Program Database (PDB) des NT-Kernels entnehmen. Ich habe jedoch beobachtet, dass nicht jedes der drei Dumpformate auch alle verfügbaren Felder ausnutzt.

OffsetTypFeldBemerkungen
0x000charSignature[4]'PAGE'
0x004charValidDump[4]'DUMP'
0x008uint32MajorVersion
0x00cuint32MinorVersionNummer der Windows Build
0x010uint32DirectoryTableBase
0x014uint32PfnDataBase
0x018uint32PsLoadedModuleList
0x01cuint32PsActiveProcessHead
0x020uint32MachineImageType
0x024uint32NumberProcessors
...
0x05ccharPaeEnabled
...
0x064charPhysicalMemoryBlockBuffer[700]
...
0xf88uint32DumpType1 = full dump, 2 = kernel dump (kleiner)
...
0xfa0int64RequiredDumpSpacesollte der Dateigröße entsprechen
...
0xfb8int64SystemUpTimegemessen in Einheiten zu 100 ns
0xfc0int64SystemTimeFILETIME
...

Und so sieht der Header in einem Hex-Editor aus. Beachten Sie, dass unbenutzte Bereiche mit "PAGEDUMP" gefüllt sind:

Dump File Header

Ich werde mich im Weiteren auf den PhysicalMemoryBlockBuffer konzentrieren, weil diese Sub-Struktur die benötigten Informationen zur Umrechnung physischer Adressen in Offsets des Dumps enthält. Wenn Sie das Programm dumpchk der Microsoft Debugging Tools ausführen, dann zeigt es Ihnen neben vielen anderen Dingen auch folgendes an:

Physical Memory Description:
Number of runs: 4
          FileOffset  Start Address  Length
           00001000     00002000     0001e000
           0001f000     00030000     0006f000
           0008e000     00100000     00eff000
           00f8d000     01000000     2e740000
Last Page: 2f6cc000     2f73f000

Das sind genau die so dringend benötigten Informationen! Es stellt sich jedoch die Frage, wo diese Informationen im Dump enthalten sind und wie sie sich lesbar machen lassen.

In dem Screenshot aus dem Hex-Editor habe ich die entsprechende Region blau markiert. Umdie Darstellung etwas zu erleichtern, habe ich dann ein Template für den 010 Editor geschrieben. Es interpretiert den PhysicalMemoryBlockBuffer entsprechend der nachfolgend beschriebenen Strukturen:

typedef struct {
	uint32 BasePage;
	uint32 PageCount;
} _PHYSICAL_MEMORY_RUN32;

typedef struct {
uint32 NumberOfRuns;
uint32 NumberOfPages;
_PHYSICAL_MEMORY_RUN32 Run[NumberOfRuns];
} _PHYSICAL_MEMORY_DESCRIPTOR32;

Hier ist das Ergebnis:

Der interpretierte PhysicalMemoryBlockBuffer.

Alle Längen und Offsets werden in Speicherseiten gemessen, also in Einheiten zu 4096 Bytes (0x1000 in hexadezimaler Notation). Wie Sie bei genauer Betrachtung sehen können, enthält der Dump kein kontinuierliches Abbild des physischen Speichers. Auch gibt es einige Löcher, das Abbild ist also nicht vollständig.

Nehmen Sie als Beispiel den ersten Block ("run"). Er beginnt mit Speicherseite 2 und enthält 0x1e Seiten. Die letzte Seite in diesem Block ist also 0x1f. Der nächste Block beginnt aber mit Seite 0x30. Im Abbild fehlen also die Seiten von 0x20 bis 0x2f. Dieser Sachverhalt lässt sich auch im Debugger überprüfen (Bitte beachten Sie das Ausrufzeichen im Kommando, es bezeichnet virtuelle Adressen statt der üblichen virtuellen):

kd> !db 20000
Physical memory read at 20000 failed
If you know the caching attributes used for the memory,
try specifying [c], [uc] or [wc], as in !dd [c] .
WARNING: Incorrect use of these flags will cause unpredictable
processor corruption.  This may immediately (or at any time in
the future until reboot) result in a system hang, incorrect data
being displayed or other strange crashes and corruption.

Auf Grundlage der Informationen aus dem PhysicalMemoryBlockBuffer lässt sich nun auch der Offset innerhalb des Speicherabbildes zu einer gegebenen physischen Adresse berechnen. Als Beispiel soll der String an der physischen Adresse 0x120056 im Abbild lokalisiert werden. Die Adresse liegt in der Speicherseite 0x120, mit einem Offset von 0x056 Bytes.

Seite 0x120 ist im Block Nr. 2 (der mit der Seite 0x100 beginnt) mit einem Offset von 0x20 Seiten. Nun sind die ganzen Offsets zu addieren:

  0x20 Seiten Offset in Block 2
+ 0x6f seiten in Block 1
+ 0x1e Seiten in Block 0
+ 0x01 Seite für den Header der DMP Datei
= 0xae Seiten
= 0xae * 0x1000 Bytes
= 0xae000 Bytes Offset im Speicherabbild.

Hierzu kommt noch der Offset des Strings innerhalb seiner Speicherseite: 0xae000 + 0x56 = 0xae056. Das ist der endgültige Offset.

Der gesuchte String im Hex-Editor.

Zum Vergleich ist hier noch einmal der selbe Bereich im Debugger dargestellt:

Der gleiche Speicherbereich im Debugger.

Ich hoffe, dass es diese Beschreibung den Autoren diverser Programme zur Speicheranalyse ermöglichen wird, in Zukunft auch das DMP Format auszuwerten.

Nachtrag 09.10.2006: Bei der Auswertung des Dumps kann sich der Microsoft Kernel Memory Space Analyzer als nützlich erweisen.

26.06.2007: Korrektur eines Tippfehlers im Offset für RequiredDumpSpace.

28.02.2008: Bitte beachten Sie auch den Artikel über 64bit-Crash Dumps.

Archiv

Impressum

Dieses Blog ist ein Projekt von:
Andreas Schuster
Im Äuelchen 45
D-53177 Bonn
impressum@forensikblog.de

Copyright © 2005-2012 by
Andreas Schuster
Alle Rechte vorbehalten.
Powered by Movable Type 5.12