| Sulaiman Chang Personal Website |
|
Windows PE File Format Walkthrough I Sulaiman Chang September 9, 2004 Presented is a step by step approach to understand the windows PE file format. First, we will build a simple windows .exe executable and we will then go to analyze it byte by byte.
format PE GUI 4.0
entry start
include '%fasminc%\win32a.inc'
section '.data' data readable writeable
msgText db 'Message Text',0
msgCaption db 'Message Caption',0
section '.code' code readable executable
start:
invoke MessageBox,HWND_DESKTOP,msgText,msgCaption,MB_OK + MB_ICONINFORMATION
invoke ExitProcess,0
section '.idata' import data readable
library KERNEL32, 'KERNEL32.DLL',\
USER32, 'USER32.DLL'
import KERNEL32,\
ExitProcess, 'ExitProcess'
import USER32,\
MessageBox, 'MessageBoxA'
this is the what you should see if you have assembled and executed it.
now, i dump the file in hex and construct it using DB only so we could examine it step by step. Of course, you could try copy the below hex code and assemble it using your favourite assembler. db 0x4D,0x5A,0x80,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0xFF,0xFF,0x00,0x00,\ 0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,\ 0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,0x21,0xB8,0x01,0x4C,0xCD,0x21,0x54,0x68,\ 0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x63,0x61,0x6E,0x6E,0x6F,\ 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x44,0x4F,0x53,0x20,\ 0x6D,0x6F,0x64,0x65,0x2E,0x0D,0x0A,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x50,0x45,0x00,0x00,0x4C,0x01,0x03,0x00,0x9E,0xA2,0x46,0x41,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0xE0,0x00,0x8F,0x81,0x0B,0x01,0x01,0x37,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,\ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x46,0xA7,0x00,0x00,0x02,0x00,0x00,0x00,\ 0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x30,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x64,0x61,0x74,0x61,0x00,0x00,0x00,\ 0x1D,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xC0,\ 0x2E,0x63,0x6F,0x64,0x65,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x20,0x00,0x00,\ 0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x60,0x2E,0x69,0x64,0x61,0x74,0x61,0x00,0x00,\ 0x90,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x06,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x40,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x4D,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x54,0x65,0x78,0x74,0x00,0x4D,0x65,0x73,\ 0x73,0x61,0x67,0x65,0x20,0x43,0x61,0x70,0x74,0x69,0x6F,0x6E,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x6A,0x40,0x68,0x0D,0x10,0x40,0x00,0x68,0x00,0x10,0x40,0x00,0x6A,0x00,0xFF,0x15,\ 0x7A,0x30,0x40,0x00,0x6A,0x00,0xFF,0x15,0x5C,0x30,0x40,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x54,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x30,0x00,0x00,\ 0x5C,0x30,0x00,0x00,0x72,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x49,0x30,0x00,0x00,0x7A,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x45,0x52,0x4E,\ 0x45,0x4C,0x33,0x32,0x2E,0x44,0x4C,0x4C,0x00,0x55,0x53,0x45,0x52,0x33,0x32,0x2E,\ 0x44,0x4C,0x4C,0x00,0x64,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x30,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x78,0x69,0x74,0x50,0x72,0x6F,0x63,0x65,0x73,\ 0x73,0x00,0x82,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x30,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x4D,0x65,0x73,0x73,0x61,0x67,0x65,0x42,0x6F,0x78,0x41,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00if you have copied the above code and assembled it, you would get exactly the same as what we got at first. The first 64 bytes (0 to 63 bytes) of our PE file is occupied by a structure named "IMAGE_DOS_HEADER". Below is the "IMAGE_DOS_HEADER" structure that was declared inside "WINNT.H" file.
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
so, now we got some idea, what our first 64 bytes actually was, so we construct it again then link the rest of our code with the above "db" hex values.
IMAGE_DOS_HEADER: ;start : 00 (0) to 3F (63)
.e_magic dw 0x5A4D ;00 01
.e_cblp dw 0x0080 ;02 03
.e_cp dw 0x0001 ;04 05
.e_crlc dw 0x0000 ;06 07
.e_cparhdr dw 0x0004 ;08 09
.e_minalloc dw 0x0010 ;10 11
.e_maxalloc dw 0xFFFF ;12 13
.e_ss dw 0x0000 ;14 15
.e_sp dw 0x0140 ;16 17
.e_csum dw 0x0000 ;18 19
.e_ip dw 0x0000 ;20 21
.e_cs dw 0x0000 ;22 23
.e_lfarlc dw 0x0040 ;24 25
.e_ovno dw 0x0000 ;26 27
.e_res rw 4 ;28 29 | 30 31 | 32 33 | 34 35
.e_oemid dw 0x0000 ;36 37
.e_oeminfo dw 0x0000 ;38 39
.e_res2 rw 10 ;40 41 | 42 43 | 44 45 | 46 47 | 48 49 | 50 51
.e_lfanew dd 0x00000080 ;52 53 | 54 55 | 56 57 | 58 59
;60 61 62 63
db 0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,0x21,0xB8,0x01,0x4C,0xCD,0x21,0x54,0x68,\
.......... ...... ..... .... ... .. .(until the end)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
According to most of the tutorial i read on this subject, we only need to concern on 2 members of this IMAGE_DOS_HEADER structure which are, e_magic and e_lfanew. e_magic value "4D5A" is equal to "MZ" if we translated that value into ASCII while e_lfanew value "00 00 00 80" (we need to reverse read it in order to get the value) is the pointer or address to our IMAGE_NT_HEADERS structure. Before we could move our way to IMAGE_NT_HEADERS, there exists a DOS 2.0 Stub Program which lays between them. This stub program occupies the address from 0x40 to 0x77 generally then we add 8 bytes so that we could start our IMAGE_NT_HEADERS in paragraph boundary in 0x80.
The DOS 2.0 Stub Program is a 16-bit instruction. so, we simply just use our windows provided debug program to see what are the instructions contained inside.
Microsoft Windows 2000 [Version 4.00.0000]
(C) Copyright 1985-1999 Microsoft Corp.
H:\tutorial>debug pe3.exe
-u
1597:0000 0E PUSH CS
1597:0001 1F POP DS
1597:0002 BA0E00 MOV DX,000E
1597:0005 B409 MOV AH,09
1597:0007 CD21 INT 21
1597:0009 B8014C MOV AX,4C01
1597:000C CD21 INT 21
OUR DATA SECTION STARTS FROM HERE
=================================
1597:000E 54 PUSH SP -> T
1597:000F 68 DB 68 -> h
1597:0010 69 DB 69 -> i
1597:0011 7320 JNB 0033 -> s (space bar)
1597:0013 7072 JO 0087 -> p r
1597:0015 6F DB 6F -> o
1597:0016 67 DB 67 -> g
1597:0017 7261 JB 007A -> r a
1597:0019 6D DB 6D -> m
1597:001A 206361 AND [BP+DI+61],AH -> (space bar) c a
1597:001D 6E DB 6E -> n
1597:001E 6E DB 6E -> n
1597:001F 6F DB 6F -> o
159A:0020 7420 JZ 0042 -> t (space bar)
159A:0022 62 DB 62 -> b
159A:0023 65 DB 65 -> e
159A:0024 207275 AND [BP+SI+75],DH -> (space bar) r u
159A:0027 6E DB 6E -> n
159A:0028 20696E AND [BX+DI+6E],CH -> (space bar) i n
159A:002B 20444F AND [SI+4F],AL -> (space bar) D O
159A:002E 53 PUSH BX -> S
159A:002F 206D6F AND [DI+6F],CH -> (space bar) m o
159A:0032 64 DB 64 -> d
159A:0033 65 DB 65 -> e
159A:0034 2E CS: -> .
159A:0035 0D0A24 OR AX,240A -> (carriage return) (line feed) $
159A:0038 0000 ADD [BX+SI],AL -> 00 00
159A:003A 0000 ADD [BX+SI],AL -> 00 00
159A:003C 0000 ADD [BX+SI],AL -> 00 00
159A:003E 0000 ADD [BX+SI],AL -> 00 00
-
this is what we get if we unassemble our created PE file using the DEBUG program. The debug program won't unassemble our IMAGE_DOS_HEADER because it is already been replaced with PSP (Program Segment Prefix). One thing we need to concern here is our initial or start-up register values.
-r AX=0000 BX=0000 CX=0600 DX=0000 SP=0140 BP=0000 SI=0000 DI=0000 DS=158A ES=158A SS=159A CS=159A IP=0000 NV UP EI PL NZ NA PO NC 159A:0000 0E PUSH CSThe loader sets our DS and ES to the address of PSP and sets the CS, IP, SS and SP to values from our IMAGE_DOS_HEADER structure. The reason we need to PUSH CS and POP DS is to initialize our DS so that it is the same as CS so that nothing wrong when we use the instruction MOV DX,000E. i guess now, we got the information to code our dos-stub program.
DOS_STUB:
org 0 ;because our initial IP was 0
use16 ;DOS-STUB is a 16-bit program
push cs
pop ds ;our DS is less 100h from CS, DS received PSP address
mov dx,errMsg
mov ah,0x9
int 0x21
mov ax,0x4C01
int 0x21
errMsg db 'This program cannot be run in DOS mode.',13,10,'$'
org $ + DOS_STUB ;is equal to 0x38 + 0x40 = 0x78
rb 0x80 - $ ;0x80 - 0x78 = rb 0x8
you might not prefer the idea to have ORG and ORG again, so how could we do it without the ORG. To code without using the ORG, we just use the address directly, example like below.
DOS_STUB:
use16 ;DOS-STUB is a 16-bit program
push cs
pop ds ;our DS is less 100h from CS, DS received PSP address
mov dx,0x0E ;is 0x0E because our data start at 1597:000E in below unassemble
mov ah,0x9
int 0x21
mov ax,0x4C01
int 0x21
db 'This program cannot be run in DOS mode.',13,10,'$'
rb 0x80 - $ ;0x80 - 0x78 = rb 0x8
... 1597:000E 54 PUSH SP --> This program cannot be run in DOS mode. ...i am the minimalist type, so, i choose to modify it not to initialize the DS because i use the DS for one time only in my DOS Stub Program.
DOS_STUB: ;start : 40 (64) to 7F (127)
use16 ;DOS-STUB is a 16-bit program
;push cs <- we save 1 byte here
;pop ds <- we save another 1 byte here
;our DS is less 100h from CS, DS received PSP address
mov dx,0x100 + 0x0B ;our db message starts at 0x0B because we save 3 bytes already
mov ah,0x9
int 0x21
mov ah,0x4C ;save 1 byte here because we need to use AH only for function
int 0x21
db 'This program cannot be run in DOS mode.',13,10,'$'
rb 0x80 - $ ;0x80 - 0x75 = rb 0xB
so far, we already cover the IMAGE_DOS_HEADER and DOS 2.0 STUB PROGRAM, we will continue to IMAGE_NT_HEADERS in our next walkthrough.
PE File Format (so far) ======================= 0x00 .... 0x3F ------------------------------- IMAGE_DOS_HEADER 0x40 .... 0x7F ------------------------------- DOS 2.0 Stub Program 0x80 .... ? ------------------------------- IMAGE_NT_HEADERSContinue to Windows PE File Format Walkthrough II |
| Copyright © 2004 Sulaiman Chang. All Rights Reserved. |