PE格式概貌,以下只是PE格式的大致结构
+---------------+
| DOS MZ header |
+---------------+
| DOS stub |
+---------------+
| PE header |
+---------------+
| Section table |
+---------------+
| Section 1 |
+---------------+
| Section 2 |
+---------------+
| Section ... |
+---------------+
| Section n |
+---------------+
1) DOS MZ header
这一模块有64个字节(大都如此),我们所关心的是开始和结尾的四个字节.
开始的四个字节是 16BIT的标志位IMAGE_DOS_HEADER 4D 5A(ASC2码就是'MZ')
最后的四个字节是 从文件起始到PE header模块的偏移量.
2) DOS STUB
这一模块没有什么好说的.实际上是个有效的EXE,在不支持 PE文件格式的操作系统中,
它将简单显示一个错误提示,类似于字符串 "This program requires Windows"
3) PE header
这一模块比较重要.包含很多重要的信息(如:支持在什么样的机器上运行,有多少section
是EXE还是DLL等.这个模块的起始地址可由DOS MZ header模块的的最后四个字节读出。
如读到的是 E0 00 00 00则此模块的起始地址是0000000E,这样PE LOADER可根据此地址跳过
DOS STUB直接定位到此模块。
4) section table
PE格式真正的内容都是以section为单位的,section table是一个结构数组,该数组中成员的
个数就是该文件的SECTION个数,由PE header模块读出。每个SECTION对应一个结构其
包含对应节的属性、文件偏移量、虚拟偏移量等。
5) 以下就是各个SECTION的内容了 比如:
.text section 其中包含着代码,所有 OBJ 文件中的代码都被合并到这个section 里。
.data section 中为所有已初始化的数据以及静态的数据;
.bss section 里装的是未初始化的数据;
.rdata section 里包含字符串和常量之类的只读数据还有其它只读结构,如 debug directory(即.pdb 文件的路径,见下文dumpbin /headers xxx.exe文件内容)、 Thread Local Storage (TLS) directory 等等,
.edata section 里保存着从 DLL 中 exported 的函数的信息;(用dumpbin查找了几个DLL,发现竟然没有.edata section,通过查看export directory 发现,export信息被放在了.rdata section。见此文章评论)
.idata section 则保存着从可执行文件/DLL 中的 imported 函数的信息。
.rsrc section 包含着各种资源的数据,比如菜单和对话框。
.reloc section 保存着加载程序时所需的重定位信息。
了解了大概的模块让我们看看PE LOADER的装载顺序:.当PE文件被执行,PE装载器检查DOS MZ header 里的PE header 偏移量。 如果找到,则跳转到PE header。PE装载器检查 PE header 的有效性。如果有效,就跳转到PE header的尾部。紧跟PE header 的是节表。PE装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时付上节表里指定的节属性。PE文件映射入内存后,PE装载器将处理PE文件中类似 import table(引入表)逻辑部分。
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://cjbskysea.blogbus.com/logs/74906879.html
具体数据结构:
1.Image DOS Header和DOS Stub是为了兼容DOS系统
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number ‘M’’Z’
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;
a) e_ip和e_cs指向DOS Stub,DOS Stub是DOS下运行的一小段代码,输出”This programme cannot be run in DOS”,然后退出程序。
b) 对windows有用参数为e_lfanew,标识了IMAGE_NT_HEADERS在PE文件中的偏移。
2.PE File Header是PE文件的真正文件头
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;//0x
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
a)Image Header
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
b) Image Optional Header
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;//Preferred address of the first byte of the image when it is loaded in memory. The default value for DLLs is 0x10000000. The default value for applications is 0x00400000.
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
3.Section Table:保存各段的基本信息
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
4. 各段具体内容
…
5.dumpbin /headers xxx.exe
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file 4.exe PE signature found File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (x86) 6 number of sections 4E3F472D time date stamp Mon Aug 08 10:17:17 2011 0 file pointer to symbol table 0 number of symbols E0 size of optional header 103 characteristics Relocations stripped Executable 32 bit word machine OPTIONAL HEADER VALUES 10B magic # (PE32) 8.00 linker version 58000 size of code 16000 size of initialized data 0 size of uninitialized data 2BD8E entry point (0042BD8E) @ILT+3465(_main) 1000 base of code 1000 base of data 400000 image base (00400000 to 00498FFF) 1000 section alignment 1000 file alignment 4.00 operating system version 0.00 image version 4.00 subsystem version 0 Win32 version 99000 size of image 1000 size of headers 0 checksum 3 subsystem (Windows CUI) 0 DLL characteristics 100000 size of stack reserve 1000 size of stack commit 100000 size of heap reserve 1000 size of heap commit 0 loader flags 10 number of directories 0 [ 0] RVA [size] of Export Directory 97000 [ 28] RVA [size] of Import Directory 98000 [ C09] RVA [size] of Resource Directory 0 [ 0] RVA [size] of Exception Directory 0 [ 0] RVA [size] of Certificates Directory 0 [ 0] RVA [size] of Base Relocation Directory 83C50 [ 1C] RVA [size] of Debug Directory 0 [ 0] RVA [size] of Architecture Directory 0 [ 0] RVA [size] of Global Pointer Directory 0 [ 0] RVA [size] of Thread Storage Directory 0 [ 0] RVA [size] of Load Configuration Directory 0 [ 0] RVA [size] of Bound Import Directory 97210 [ 1E8] RVA [size] of Import Address Table Directory 0 [ 0] RVA [size] of Delay Import Directory 0 [ 0] RVA [size] of COM Descriptor Directory 0 [ 0] RVA [size] of Reserved Directory SECTION HEADER #1 .textbss name 29AED virtual size 1000 virtual address (00401000 to 0042AAEC) 0 size of raw data 0 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 E00000A0 flags Code Uninitialized Data Execute Read Write SECTION HEADER #2 .text name 57748 virtual size 2B000 virtual address (0042B000 to 00482747) 58000 size of raw data 1000 file pointer to raw data (00001000 to 00058FFF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 60000020 flags Code Execute Read SECTION HEADER #3 .rdata name FAE1 virtual size 83000 virtual address (00483000 to 00492AE0) 10000 size of raw data 59000 file pointer to raw data (00059000 to 00068FFF) 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 Read Only Debug Directories Time Type Size RVA Pointer -------- ------ -------- -------- -------- 4E3F472A cv 2D 00090F18 66F18 Format: RSDS, {220901B2-E313-4B36-8F2F-DAA133F4CA37}, 2, e:\tmp\4\debug\4.pdb SECTION HEADER #4 .data name 3914 virtual size 93000 virtual address (00493000 to 00496913) 2000 size of raw data 69000 file pointer to raw data (00069000 to 0006AFFF) 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 Read Write SECTION HEADER #5 .idata name C64 virtual size 97000 virtual address (00497000 to 00497C63) 1000 size of raw data 6B000 file pointer to raw data (0006B000 to 0006BFFF) 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 Read Write SECTION HEADER #6 .rsrc name C09 virtual size 98000 virtual address (00498000 to 00498C08) 1000 size of raw data 6C000 file pointer to raw data (0006C000 to 0006CFFF) 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 Read Only Summary 4000 .data 1000 .idata 10000 .rdata 1000 .rsrc 58000 .text 2A000 .textbss