Windows下所谓PE文件即Portable Executable,意为可移植的可执行的文件。常见的.EXE、.DLL、.OCX、.SYS、.COM都是PE文件。PE文件有一个共同特点:前两个字节为4D 5A(MZ)。如果一个文件前两个字节不是4D 5A则其肯定不是可执行文件。比如用16进制文本编辑器打开一个“.xls”文件其前两个字节为:0XD0 0XCF;打开一个“.pdf”其前两个字节为:0X25 0X50。
PE文件结构:DOS头+PE头+节表+.data/.rdata/.text。而今天我们就来具体了解一下PE文件的DOS头和PE头的结构成员与部分成员的作用。注意:一个exe文件本身是一个PE文件,但是由于包含dll库,所以一个exe文件也是许多PE文件组成的(包含多个dll)一个PE文件。
本文中所用到的实例程序write.exe存放路径位于本机的C:\Windows目录下,是利用WinHex编译器来打开的。
1、DOS头:共40H(64字节)
DOS头中声明用的寄存器(我们可以看到e_ss、e_sp、e_ip、e_cs还是16位的寄存器),所以在32位/64为系统中用到的只有两个成员了(第一个和最后一个),也是我们务必要记住的:
①e_magic:判断一个文件是不是PE文件;
②e_lfanew:相对于文件首的偏移量,用于找到PE头;
具体结构如下(前面的十六进制数表示该成员相对于结构的偏移量,WORD2字节变量、DWORD4字节变量):
//注释掉的不需要重点分析
struct _IMAGE_DOS_HEADER{
0X00 WORD e_magic; //※Magic DOS signature MZ(4Dh 5Ah):MZ标记:用于标记是否是可执行文件
//0X02 WORD e_cblp; //Bytes on last page of file
//0X04 WORD e_cp; //Pages in file
//0X06 WORD e_crlc; //Relocations
//0X08 WORD e_cparhdr; //Size of header in paragraphs
//0X0A WORD e_minalloc; //Minimun extra paragraphs needs
//0X0C WORD e_maxalloc; //Maximun extra paragraphs needs
//0X0E WORD e_ss; //intial(relative)SS value
//0X10 WORD e_sp; //intial SP value
//0X12 WORD e_csum; //Checksum
//0X14 WORD e_ip; //intial IP value
//0X16 WORD e_cs; //intial(relative)CS value
//0X18 WORD e_lfarlc; //File Address of relocation table
//0X1A WORD e_ovno; //Overlay number
//0x1C WORD e_res[4]; //Reserved words
//0x24 WORD e_oemid; //OEM identifier(for e_oeminfo)
//0x26 WORD e_oeminfo; //OEM information;e_oemid specific
//0x28 WORD e_res2[10]; //Reserved words
0x3C DWORD e_lfanew; //※Offset to start of PE header:定位PE文件,PE头相对于文件的偏移量
};
我们查看下面所示write.exe文件的结构信息:
64字节(共4行)的DOS头,第一个成员2个字节是可执行文件的标志信息;最后一个成员4字节是PE头的偏移地址为000000E0H,我们可以根据000000E0H来获取PE头的地址。而DOS头和PE头中间的空余位置是一些垃圾值以及编译器填充的一些“is program cannot be run in DOS mode.”或“This program must be run under Win32