PE文件格式
PE文件包括DOS部分、PE文件头和节表和节数据。从DOS头(DOS header)到节区头(Sectionheader)是PE头部分,其下的节区合称PE体。节数据包括代码(.text)、数据(.data)、资源(.rsrc)节,分别保存。
1.DOS部分:
- IMAGE_DOS_HEADER (MZ文件头 0x40)
IMAGE_DOS_HEADER结构体的大小为40字节,需要注意的2个重要成员:
0x0-0x01 | e_magic: DOS签名,表文件开始标识 | 0x4d5a=”MZ” |
0x3c-0x3f | e_lfanew:PE头部分的偏移 | 0x000000b0. |
- dos stub
DOS存根位于DOS头下方,是个可选项,且大小不固定,即使没有DOS存根,文件也能正常运行,DOS存根由代码与数据混合而成。
2.PE头部分:IMAGE_NT_HEADERS
IMAGE_NT_HEADERS结构体大小为F8,由3个成员组成,第一个成员为签名结构体,其值为50450000h("PE"00),另外两个成员分别为文件头与可选头结构体。
- signature(0x04字节)
0x00-0x03 | PE标记,PE\0\0 | 50h 45h 00h 00h |
- IMAGE_FILE_HEADER 映像文件头(0x14字节)
0x04-0x05 | machine | 0x014c=”x86” |
0x06-0x07 | NumberOfSections文件中节的个数 | 0x0003=3 |
0x14-0x15 | SizeOfOptionalHeader:可选文件头大小 | 0x000e=14 |
- IMAGE_OPTIONAL_HEADER()
0x28-0x2b | AddressOfEntryPoint, RVA值,代码起始地址 | 0x00001000 |
0x34-0x37 | ImageBase,文件的优先装入地址,基址。 文件地址:ImageBase+AddressOfEntryPoint=0x401000. | 0x00400000 |
0x38-0x3b | SectionAlignment,内存中的对齐粒度 | 0x1000 |
0x3c-0x3f | FileAlignment,文件中的对齐粒度 | 0x200 |
0x74-0x77 | NumberOfRvaAndSIzes 用来指定数据目录列表data_directory的个数。 | 0x00000010 |
SizeOfImage
加载PE文件到内存时,SizeOfImage指定了PE Image在虚拟内存中所占空间的大小,一般而言,文件的大小与加载到内存的大小是不同的。
SizeofHeader
用来指出整个PE头的大小,该值也必须是FileAlignment的整数倍。
(3)节表IMAGE_SECTION_HEADER
可以看到有三个节表项,text,rdata,data,每个节表项是40字节
0x0-0x7 | 节表名称,例如“.text” 或者code | 2e 74 65 78 74 .text 63 6f 64 65 code |
0x8-0xB | Virtual size , 内存中大小(内存对齐前的长度),即节区真实大小 因为内存的对齐粒度是0x1000 所以,节区在内存中的大小是0x1000 因为文件的对齐粒度是0x200 所以,节区在文件中的大小是0x200 | 0x00000046 |
0x0c-0x0f | VirtualAddress:内存中节区RVA 所以,在内存中的实际地址为: Imagebase+virtualaddress=0x401000 | 0x00001000 |
0x10-0x13 | SizeOfRawData:文件中大小(文件对齐后的长度) | 0x00000200 (46<200) |
0x14-0x17 | PointerToRawData:文件中节区RVA | 0x00000400 |
0x24-0x27 | Characteristics:节区属性 | 0x60000020 |
节的解析请看下一章