PE文件结构入门
字数 1278 2025-08-09 17:09:26
PE文件结构详解
一、PE文件概述
1.1 可执行文件类型
- Windows平台: PE(Portable Executable)文件结构
- Linux平台: ELF(Executable and Linking Format)文件结构
1.2 PE文件应用领域
- 病毒与反病毒
- 外挂与反外挂
- 加壳与脱壳
- 无源码修改功能/汉化
1.3 PE文件识别特征
- 前两字节ASCII是"MZ"
- 0x3C位置的十六进制对应ASCII是"PE"
二、PE文件结构详解
2.1 DOS部分
typedef struct _IMAGE_DOS_HEADER {
WORD e_magic; // Magic number "MZ" (0x4D5A)
// ...其他DOS头字段...
LONG e_lfanew; // PE头相对文件起始地址的偏移
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
- DOS头大小: 64字节(18个WORD + 1个LONG)
- 关键字段:
e_magic: 必须为"MZ"(0x4D5A)e_lfanew: 指向PE头的偏移
2.2 PE文件头
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; // "PE\0\0" (0x00004550)
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
2.2.1 标准PE头(IMAGE_FILE_HEADER)
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; // 运行平台标识
WORD NumberOfSections; // 节表数量
DWORD TimeDateStamp; // 创建时间戳
DWORD PointerToSymbolTable; // COFF符号表偏移
DWORD NumberOfSymbols; // 符号表数量
WORD SizeOfOptionalHeader; // 扩展PE头大小
WORD Characteristics; // 文件属性标志
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
2.2.2 扩展PE头(IMAGE_OPTIONAL_HEADER)
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; // 标识32/64位(0x10B/0x20B)
// ...其他字段...
DWORD AddressOfEntryPoint; // 程序执行入口RVA
DWORD ImageBase; // 首选装载地址
DWORD SectionAlignment; // 内存对齐大小
DWORD FileAlignment; // 文件对齐大小
// ...其他字段...
IMAGE_DATA_DIRECTORY DataDirectory[16]; // 数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
2.2.3 数据目录表
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress; // RVA
DWORD Size; // 大小
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
重要目录项:
- 0: 导出表
- 1: 导入表
- 2: 资源表
- 5: 重定位表
- 9: TLS目录
- 12: 导入地址表(IAT)
2.3 节表
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[8]; // 节区名称
union {
DWORD PhysicalAddress;
DWORD VirtualSize; // 节区的实际尺寸
} Misc;
DWORD VirtualAddress; // 节区的RVA地址
DWORD SizeOfRawData; // 文件中对齐后的尺寸
DWORD PointerToRawData; // 文件中的偏移量
// ...其他字段...
DWORD Characteristics; // 节属性(可读/可写/可执行等)
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
2.4 节数据
- 包含实际的代码、数据等内容
- 按照节表定义的位置和大小排列
三、PE文件两种状态
3.1 磁盘状态
- 节按照
FileAlignment对齐(通常200h) - 未初始化数据不占用磁盘空间
3.2 内存状态
- 节按照
SectionAlignment对齐(通常1000h) - 未初始化数据分配内存空间
- 部分节(.reloc等)不映射到内存
四、关键操作技术
4.1 RVA与FOA转换
- 判断RVA是否位于PE头:
- 是: FOA = RVA
- 定位所属节:
- RVA >= 节.VirtualAddress
- RVA <= 节.VirtualAddress + 内存对齐后大小
- 计算差值 = RVA - 节.VirtualAddress
- FOA = 节.PointerToRawData + 差值
4.2 空白区添加代码
步骤:
- 构造要写入的代码
- 在PE空白区插入代码
- 修改入口地址指向新增代码
- 新增代码执行后跳回原入口
4.3 扩大节
步骤:
- 分配新空间(大小S)
- 修改最后一个节的SizeOfRawData和VirtualSize
- N = 原值(对齐后) + S
- 修改SizeOfImage的值
4.4 新增节
步骤:
- 检查是否有足够空间添加节表
- 在节表中新增成员
- 修改PE头中节的数量
- 修改SizeOfImage大小
- 在文件末尾添加节数据(内存对齐整数倍)
- 设置新增节表属性
五、重要数据表
5.1 导出表
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name; // 模块名RVA
DWORD Base; // 序号基数
DWORD NumberOfFunctions; // 导出函数总数
DWORD NumberOfNames; // 按名导出函数数
DWORD AddressOfFunctions; // 函数地址表RVA
DWORD AddressOfNames; // 函数名指针表RVA
DWORD AddressOfNameOrdinals; // 序号表RVA
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
5.2 导入表
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk; // 导入名称表(INT)RVA
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name; // DLL名RVA
DWORD FirstThunk; // 导入地址表(IAT)RVA
} IMAGE_IMPORT_DESCRIPTOR;
5.3 重定位表
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress; // 页起始RVA
DWORD SizeOfBlock; // 该分组大小
WORD TypeOffset[1]; // 重定位项数组
} IMAGE_BASE_RELOCATION;
- 重定位类型: IMAGE_REL_BASED_HIGHLOW(3)
- 每个WORD: 高4位为类型,低12位为偏移
六、总结
PE文件结构是Windows平台可执行文件的核心组织形式,理解其结构对于软件安全分析、逆向工程、病毒分析等领域至关重要。掌握DOS头、PE头、节表及各数据目录的结构和相互关系,能够帮助深入分析PE文件的行为和特性。