本节与PE文件格式相关的术语以<<微软PE/COFF规范>>为准([13]),不再强调该点。 winnt.h中定义了部分相关数据结构,后面如未单独注明来自哪个头文件,均隐指来 自winnt.h。执行vulnerable_0.exe,进入windbg调试状态。
> !list -t _LIST_ENTRY.Flink -x "dd" -a "+18 L1" 241ec0 00241ed8 00400000 00241f30 77f50000 00241fd8 77e60000 ... ...
从上节可知,ntdll.dll基址是0x77f50000,kernel32.dll基址是0x77e60000。最开 始的64字节按如下数据结构解析:
-------------------------------------------------------------------------- #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
typedef struct _IMAGE_DOS_HEADER // DOS .EXE header {
WORD e_magic; // +0x00 Magic number WORD e_cblp; // +0x02 Bytes on last page of file WORD e_cp; // +0x04 Pages in file WORD e_crlc; // +0x06 Relocations WORD e_cparhdr; // +0x08 Size of header in paragraphs WORD e_minalloc; // +0x0a Minimum extra paragraphs needed WORD e_maxalloc; // +0x0c Maximum extra paragraphs needed WORD e_ss; // +0x0e Initial (relative) SS value WORD e_sp; // +0x10 Initial SP value WORD e_csum; // +0x12 Checksum WORD e_ip; // +0x14 Initial IP value WORD e_cs; // +0x16 Initial (relative) CS value WORD e_lfarlc; // +0x18 File address of relocation table WORD e_ovno; // +0x1a Overlay number WORD e_res[4]; // +0x1c Reserved words WORD e_oemid; // +0x24 OEM identifier (for e_oeminfo) WORD e_oeminfo; // +0x26 OEM information; e_oemid specific WORD e_res2[10]; // +0x28 Reserved words LONG e_lfanew; // +0x3c File address of new exe header // +0x40 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; --------------------------------------------------------------------------
> db 77e60000 L0n64 77e60000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. 77e60010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... 77e60020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 77e60030 00 00 00 00 00 00 00 00-00 00 00 00 f8 00 00 00 ................ > dd 77e60000+3c L1 (显示e_lfanew成员) 77e6003c 000000f8
其中e_lfanew成员用于定位PE头。从注释中理解,e_lfanew是File pointer,非RVA, 不过在这里当成RVA处理也没关系。e_lfanew值为0x000000f8,PE头在基址加0xf8的 位置。PE头最开始是标识"PE\0\0",占4字节,然后是20字节固定头。
-------------------------------------------------------------------------- #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 #define IMAGE_SIZEOF_FILE_HEADER 20
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; // +0x00 WORD NumberOfSections; // +0x02 DWORD TimeDateStamp; // +0x04 DWORD PointerToSymbolTable; // +0x08 DWORD NumberOfSymbols; // +0x0c WORD SizeOfOptionalHeader; // +0x10 WORD Characteristics; // +0x12 // +0x14 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; --------------------------------------------------------------------------
> db 77e60000+f8 L0n24 77e600f8 50 45 00 00 4c 01 04 00-28 fa 6d 3d 00 00 00 00 PE..L...(.m=.... 77e60108 00 00 00 00 e0 00 0e 21 ^^^^^ 接下来是可选头,SizeOfOptionalHeader成员表明可选头占用了224字节(0x00e0)。
-------------------------------------------------------------------------- typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; // +0x00 BYTE MajorLinkerVersion; // +0x02 BYTE MinorLinkerVersion; // +0x03 DWORD SizeOfCode; // +0x04 DWORD SizeOfInitializedData; // +0x08 DWORD SizeOfUninitializedData; // +0x0c DWORD AddressOfEntryPoint; // +0x10 DWORD BaseOfCode; // +0x14 DWORD BaseOfData; // +0x18 DWORD ImageBase; // +0x1c DWORD SectionAlignment; // +0x20 DWORD FileAlignment; // +0x24 WORD MajorOperatingSystemVersion; // +0x28 WORD MinorOperatingSystemVersion; // +0x2a WORD MajorImageVersion; // +0x2c WORD MinorImageVersion; // +0x2e WORD MajorSubsystemVersion; // +0x30 WORD MinorSubsystemVersion; // +0x32 DWORD Win32VersionValue; // +0x34 DWORD SizeOfImage; // +0x38 DWORD SizeOfHeaders; // +0x3c DWORD CheckSum; // +0x40 WORD Subsystem; // +0x44 WORD DllCharacteristics; // +0x46 DWORD SizeOfStackReserve; // +0x48 DWORD SizeOfStackCommit; // +0x4c DWORD SizeOfHeapReserve; // +0x50 DWORD SizeOfHeapCommit; // +0x54 DWORD LoaderFlags; // +0x58 DWORD NumberOfRvaAndSizes; // +0x5c Number of data-dictionary entries in the remainder of the Optional Header // +0x60 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // +0xe0 } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress; // +0x00 RVA DWORD Size; // +0x04 The size in bytes // +0x08 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIREC |