Portable Executable File Format on Memory Dump

I am going to describe how we can check PE stuffs on a file loaded on to a system in a memory dump file in this article. PE file format is the file format for Win32 Executables having extensions like .exe, .sys, .dll, etc. Here I put down on the short details of Portable Executables file format itself. PE file format is made up of IMAGE_DOS_HEADER, IMAGE_NT_HEADERS (IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER), IMAGE_SECTION_HEADERS, Sections. You can get the details on the structures of PE file format on Winnt.h. You will find further more about PE format on http://msdn.microsoft.com/en-us/library/ms809762.aspx.

How can we list the modules loaded in a memory dump file? We can use “lm n t” command to list the modules loaded on the dump file.

Here I will look into the PE on GDI32.dll listed above. We can use “!dh” to display the headers of the specified image as the followings.

0:000> !dh 77c00000

File Type: DLL

FILE HEADER VALUES

14C machine (i386)

4 number of sections

4900637A time date stamp Thu Oct 23 20:43:54 2008

0 file pointer to symbol table

0 number of symbols

E0 size of optional header

210E characteristics

Executable

Line numbers stripped

Symbols stripped

32 bit word machine

DLL

OPTIONAL HEADER VALUES

10B magic #

7.10 linker version

42400 size of code

3400 size of initialized data

0 size of uninitialized data

80A5 address of entry point

1000 base of code

—– new —–

77c00000 image base

1000 section alignment

200 file alignment

3 subsystem (Windows CUI)

5.02 operating system version

5.02 image version

4.10 subsystem version

49000 size of image

400 size of headers

4AFCC checksum

00040000 size of stack reserve

00001000 size of stack commit

00100000 size of heap reserve

00001000 size of heap commit

1CB0 [3CD6] address [size] of Export Directory

42638 [64] address [size] of Import Directory

46000 [3D0] address [size] of Resource Directory

0 [0] address [size] of Exception Directory

0 [0] address [size] of Security Directory

47000 [18B0] address [size] of Base Relocation Directory

431EC [38] address [size] of Debug Directory

0 [0] address [size] of Description Directory

0 [0] address [size] of Special Directory

0 [0] address [size] of Thread Storage Directory

25C88 [40] address [size] of Load Configuration Directory

0 [0] address [size] of Bound Import Directory

1000 [204] address [size] of Import Address Table Directory

0 [0] address [size] of Delay Import Directory

0 [0] address [size] of COR20 Header Directory

0 [0] address [size] of Reserved Directory

SECTION HEADER #1

.text name

4224A virtual size

1000 virtual address

42400 size of raw data

400 file pointer to raw data

0 file pointer to relocation table

0 file pointer to line numbers

0 number of relocations

0 number of line numbers

60000020 flags

Code

(no align specified)

Execute Read

Debug Directories(2)

TypeSizeAddressPointer

cv224322842628Format: RSDS, guid, 2, gdi32.pdb

(10)44322442624

SECTION HEADER #2

.data name

1480 virtual size

44000 virtual address

1200 size of raw data

42800 file pointer to raw data

0 file pointer to relocation table

0 file pointer to line numbers

0 number of relocations

0 number of line numbers

C0000040 flags

Initialized Data

(no align specified)

Read Write

SECTION HEADER #3

.rsrc name

3D0 virtual size

46000 virtual address

400 size of raw data

43A00 file pointer to raw data

0 file pointer to relocation table

0 file pointer to line numbers

0 number of relocations

0 number of line numbers

40000040 flags

Initialized Data

(no align specified)

Read Only

SECTION HEADER #4

.reloc name

18B0 virtual size

47000 virtual address

1A00 size of raw data

43E00 file pointer to raw data

0 file pointer to relocation table

0 file pointer to line numbers

0 number of relocations

0 number of line numbers

42000040 flags

Initialized Data

Discardable

(no align specified)

Read Only

IMAGE_DOS_HEADER

Then how can we see the details listed above? We can start to check the PE stuff of GDI32.dll from its start address with IMAGE_DOS_HEADER. The start address of GDI32.dll is 77c00000.

0:000> dt IMAGE_DOS_HEADER 77c00000

ntdll!IMAGE_DOS_HEADER

+0x000 e_magic: 0x5a4d à MZ

+0x002 e_cblp: 0x90

+0x004 e_cp: 3

+0x006 e_crlc: 0

+0x008 e_cparhdr: 4

+0x00a e_minalloc: 0

+0x00c e_maxalloc: 0xffff

+0x00e e_ss: 0

+0x010 e_sp: 0xb8

+0x012 e_csum: 0

+0x014 e_ip: 0

+0x016 e_cs: 0

+0x018 e_lfarlc: 0x40

+0x01a e_ovno: 0

+0x01c e_res: [4] 0

+0x024 e_oemid: 0

+0x026 e_oeminfo: 0

+0x028 e_res2: [10] 0

+0x03c e_lfanew: 232

The first two bytes of the specified image has 0x5a4d, which is “MZ”. We know that GDI32.dll file is a Win32 Executable from this one.

0: kd> dc b86a1000 L4

b86a100000905a4d 00000003 00000004 0000ffffMZ…………..

and the first few hundred bytes of the typical PE file are taken up by the MS-DOS stub. This stub is a tiny program that prints out something to the effect of “This program cannot be run in MS-DOS mode”. So we can check if this file supports Win32

0: kd> ?? sizeof(IMAGE_DOS_HEADER)

unsigned int 0x40

0:000> dc 77c00000+0x40 L10

77c000400eba1f0e cd09b400 4c01b821 685421cd……..!..L.!Th

77c0005070207369 72676f72 63206d61 6f6e6e61is program canno

77c0006065622074 6e757220 206e6920 20534f44t be run in DOS

77c0007065646f6d 0a0d0d2e 00000024 00000000mode….$…….

IMAGE_NT_HEADERS

The e_lfanew in the MS-DOS stub header is a relative offset (or RVA, if you prefer) to the actual PE header. To get a pointer to the PE header in memory, we just add that field’s value to the image base as the following.

The Pointer of NT Header = the Start Address of DOSHeader + DosHeader->e_lfanew;

Based on this, we can see that the signature of PE NT Header. Please note that the numeric type of e_lfanew of DOSHeader is Decimal, not Hexadecimal. So here we must add 0n to use its value as Deciaml Type.

0:000> dc 77c00000+0n232 L1

77c000e800004550PE..

Once we have a pointer to the main PE header, we can go further on NT Header. The main PE header is a structure of type IMAGE_HEADER_HEADERS, which is defined in WINNT.h. this structure is made up of a DWORD and two substructures and is laid out as follows :

0:000> dt IMAGE_NT_HEADERS 77c00000+0n232

ntdll!IMAGE_NT_HEADERS

+0x000 Signature: 0x4550 àPE\0\0

+0x004 FileHeader: _IMAGE_FILE_HEADER

+0x018 OptionalHeader: _IMAGE_OPTIONAL_HEADER

IMAGE_FILE_HEADER

Following the PE signature in the PE header is a structure of type IMAGE_FILE_HEADER, which contains the most basic information about the file. The fields of IMAGE_FILE_HEADER are show below :

0:000> dt IMAGE_FILE_HEADER 77c00000+0n232+4

ntdll!IMAGE_FILE_HEADER

+0x000 Machine: 0x14c

+0x002 NumberOfSections : 4

+0x004 TimeDateStamp: 0x4900637a

+0x008 PointerToSymbolTable : 0

+0x00c NumberOfSymbols: 0

+0x010 SizeOfOptionalHeader : 0xe0

+0x012 Characteristics: 0x210e

The value of machine field in IMAGE_FILE_HEADER is 0x14c, which is for Intel Intel 386. The number of sections are 8 from the second fields, NumberOfSections. We can check from TimeDateStamp when the linker produced this file as followings :

So you will take notice of that the analysis result based on the file structures of PE format is the same as the first block of “!dh” command output listed as following :

File Type: DLL

FILE HEADER VALUES

14C machine (i386)

4 number of sections

4900637A time date stamp Thu Oct 23 20:43:54 2008

0 file pointer to symbol table

0 number of symbols

E0 size of optional header

210E characteristics

Executable

Line numbers stripped

Symbols stripped

32 bit word machine

DLL

IMAGE_OPTIONAL_HEADER

The third part of the PE header is a structure of type IMAGE_OPTIONAL_HEADER. For PE files, this part certainly isn’t optional. We can know more details about the file through Image Optional Header : the state of the image file, the version number of the linker, the size of the code section, a pointer to the entry point function, relative to the image base address, the preferred address of the first byte of the image when it is loaded in memory, and so on. Please refer to more on its fields in http://msdn.microsoft.com/en-us/library/ms680339(vs.85).aspx

Then Where can we start to see the contents of optional header? Yes, we can find out the start offset of the image optional header from IMAGE_NT_HEADERS. Its start offset is +0x018 from the address of IMAGE_NT_HEADERS.

0:000> dt IMAGE_OPTIONAL_HEADER 77c00000+0n232+0x18

ntdll!IMAGE_OPTIONAL_HEADER

+0x000 Magic: 0x10b

+0x002 MajorLinkerVersion : 0x7 ”

+0x003 MinorLinkerVersion : 0xa ”

+0x004 SizeOfCode: 0x42400

+0x008 SizeOfInitializedData : 0x3400

+0x00c SizeOfUninitializedData : 0

+0x010 AddressOfEntryPoint : 0x80a5

+0x014 BaseOfCode: 0x1000

+0x018 BaseOfData: 0x41000

+0x01c ImageBase: 0x77c00000

+0x020 SectionAlignment : 0x1000

+0x024 FileAlignment: 0x200

+0x028 MajorOperatingSystemVersion : 5

+0x02a MinorOperatingSystemVersion : 2

+0x02c MajorImageVersion : 5

+0x02e MinorImageVersion : 2

+0x030 MajorSubsystemVersion : 4

+0x032 MinorSubsystemVersion : 0xa

+0x034 Win32VersionValue : 0

+0x038 SizeOfImage: 0x49000

+0x03c SizeOfHeaders: 0x400

+0x040 CheckSum: 0x4afcc

+0x044 Subsystem: 3

+0x046 DllCharacteristics : 0

+0x048 SizeOfStackReserve : 0x40000

+0x04c SizeOfStackCommit : 0x1000

+0x050 SizeOfHeapReserve : 0x100000

+0x054 SizeOfHeapCommit : 0x1000

+0x058 LoaderFlags: 0

+0x05c NumberOfRvaAndSizes : 0x10

+0x060 DataDirectory: [16] _IMAGE_DATA_DIRECTORY

The sum up of the Image Optional Header structure is as followings :

The state of the image file : Executable

Linker Version :7.10

The size of code section(in bytes):0x42400

A pointer to the entry point function:0x80a5

A pointer to the beginning of the code section : 0x1000

A pointer to the beginning of the data section :0x41000

The preferred address of the first byte of the image:0x77c00000

The alignment of sections loaded in memory(in bytes):0x1000 (4K)

The alignment of the raw data of sections in file:0x200 (512)

The version number of the required OS :5.02

The version number of the image :5.02

The version number of the subsystem :4.10

The size of the image (in bytes) :0x49000

The combined size of the MS-DOS stub,PE,Section hdrs:0x400

The image file checksum :0x4afcc

The subsystem required to run this image :IMAGE_SUBSYSTEM_WINDOWS_CUI (3)

The number of bytes to reserve for the stack :0x40000 (256K)

The number of bytes to commit for the stack :0x1000 (4K)

The number of bytes to reserve for the local heap :0x100000 (1MB)

The number of bytes to commit for the local heap :0x1000 (4K)

The number of directory entries :0x10 (16)

A pointer to the first IMAGE_DATA_DIRECTORY :Start Address of Optional header + 0x60

We can see that the code starts to run from “a pointer to the entry point function”. If you can have the private symbol of the file, you can see the following :