2024年5月

exe,dll,sys,com为主流可执行文件格式(pe格式)
32位pe32 64位pe32+
winnt.h有pe详细定义
pe含程序运行时所有info

layout:

ms-dos header
nt header
section header
section 实体

MS-DOS Header

DOS MZ Header
DOS STUB

IMAGE NT HEADERS

Signature
IMAGE FILE HEADERS
IMAGE
_OPTIONAL HEADERS
IMAGE DATA DIRECTORY(array lists)

Section Table

IMAGE SECTION HEADER
......
IMAGE SECTION HEADER

Sections

SECTION
SECTION
......
SECTION

实现LoadLibrary(系统默认给的pe格式),PE文件加载到内存中经过四步

  1. 要判定输入文件是否是PE格式;
  2. 要将PE文件分块按照内存映像结构放在内存中;
  3. 在IAT(Import Address Table)中,填入其依赖的导入函数地址
  4. 利用重定位表修复需要重定位的值。

PE文件加载,首先要检查的是该文件是否为PE格式,还需要检查该PE文件是否为DLL。
◎ PE的检测,需要检查的部分是MS-DOS头和NT头
◎ DLL的检测(只针对dll),检查NT头中的IMAGE_FILE_HEADER.

MS-DOS头
◎ MS-DOS头是微软为了考虑PE文件对DOS文件的兼容性而添加的。
• 大多数情况下由编译器自动生成,通常把
DOS MZ头与DOS stub合称为DOS文件头
◎ IMAGE_DOS_HEADER结构体如下图

IMAGE DOS HEADER结构体共64字节,其中两个字段比较重要,分别是e_magic
e_lfanew.

byte 1字节 word 2字节 double word 4字节

e_magic: 4D5A=>MZ 代表DOS signature
e_lfanew: NT offset address

Signature字段必须被设置为0x00004550

其中Machine,NumberOfSections,SizeOfOptionalHeader, Characteristics如果出现错误,将导致该PE文件无法正常执行。

0#1 Machine
◎该字段说明了可执行文件的目标CPU类型。
常见的一些Machine码
Machine Value
Inteli386 14Ch
MIPS R3000 162h
MIPS R4000 166h
Alpha AXP 184h
Power PC 1F0h

2 NumberOfSections

◎该字段说明了在这个PE文件中节区(Section)的数目。

3 TimeDateStamp

◎该字段说明了该PE文件是何时被创建的。

4 PointerToSymbolTable

◎该字段说明了COFF符号表(基本用不到)的文件偏移位置。COFF符号表在PE文件中较为少见,通常其值为0

SizeOfOptionalHeader
对于32位文件,该字段通常为0x00E0
对于64位文件,该字段通常为0x00F0

Magic
当IMAGE_ OPTIONAL_HEADER为
IMAGE_OPTIONAL_HEADER32(32位)时,Magic
0x10B。当其为IMAGE_OPTIONAL_HEADER64时,
Magic)70x20B.

AddressOfEntryPoint
该字段的值相对虚拟地址(加载到内存的地址),该值表明了程序最先执行的代码的启始地址,即程序入口点。

ImageBase
该字段表明了PE文件被加载进内存时,文件将被优先装入的虚拟内存的地址。对于EXE来说,ImageBase通常为0x00400000;对于DLL来说,ImageBase通常为0x10000000。装载后,EIP = ImageBase+
AddressOfEntryPoint.

SectionAlignment,FileAlignment
PE文件的Body部分划分为若干节区,FileAlignment制定了节区在文件系统中的最小单位,SectionAlignment则指定了节区在内存中的最小单位。
磁盘文件或内存的节区大小必定为FileAlignment或SectionAlignment的整数倍。

SizeOflmage
加载PE文件时,SizeOflmage指定了PE Image在虚拟内存中所占的空间大小。

SizeOfHeaders
该字段表明了整个PE文件头部的大小,该值必须是FileAlignment的整数倍。

Subsystem
该字段用于区分系统驱动文件与普通可执行文件。

NumberOfRvaAndSizes
该字段表明了下面出现的DataDirectory数组的个数。一般来说该值为16。

DataDirectory
DataDirectory是有IMAGE_DATA_DIRECTORY结构体构成的数组,数组的每项都有不同的意义。

RVA&VA(OS referance:ostep)
relative virtual address
virtual address(va)

va=image base + rva

PE文件在存储时为了减少体积,FileAlignment通常小于SectionAlignment。
当文件被映射到内存中后,同一数据在文件中的偏移量与在内存中的偏移量是不一样的,这样就存在这从文件偏移地址(RAW)到相对虚拟地址(RVA)之间的转换。
如果需要对存储在硬盘中的PE文件进行操作,需要将RVA换为RAW。