1. PE文件结构概述:可执行文件的物理与逻辑视图
当我们在Windows系统中双击一个.exe文件时,操作系统如何知道从哪里开始执行代码?程序中的函数调用和变量访问又是如何找到正确内存位置的?这些问题的答案都隐藏在PE(Portable Executable)文件结构的地址映射机制中。
PE文件是Windows操作系统下可执行文件的标准格式,它不仅包含机器代码,还承载着代码与数据在内存中的布局蓝图。理解PE文件地址映射的核心在于区分两种视角:
-
磁盘上的物理布局:PE文件在硬盘上以连续的字节序列存在,各部分按特定偏移量排列。此时所有地址都是相对于文件开头的简单偏移。
-
内存中的逻辑布局:当PE文件被加载到内存时,各段会被重新定位到不同的虚拟地址空间。此时地址需要经过复杂的映射计算。
举个例子,假设我们有一个简单的C程序编译为test.exe:
c复制#include <stdio.h>
int global_var = 42;
int main() {
printf("Address: %p\n", &global_var);
return 0;
}
编译后,global_var在磁盘文件中的位置和运行时在内存中的位置完全不同,这就是地址映射在起作用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. PE文件核心结构解析:地址映射的物理基础
2.1 PE文件头与节表的关键角色
PE文件采用分层结构设计,每一层都包含地址映射所需的关键信息:
-
DOS头(IMAGE_DOS_HEADER):
- 位于文件最开头(偏移0)
- 关键字段e_lfanew指向PE头起始位置
- 保留DOS兼容性,现代PE文件中主要起定位作用
-
PE头(IMAGE_NT_HEADERS):
- Signature:PE标识("\x50\x45\x00\x00")
- FileHeader:机器类型、节区数量等
- OptionalHeader:地址映射的核心信息源
-
节表(Section Table):
- 每个节区(如.text、.data)对应一个IMAGE_SECTION_HEADER
- 定义节区在文件和内存中的属性及位置关系
2.2 OptionalHeader中的关键地址参数
OptionalHeader(IMAGE_OPTIONAL_HEADER)包含地址计算的核心参数:
c复制typedef struct _IMAGE_OPTIONAL_HEADER {
// ...
DWORD ImageBase; // 首选加载基址(通常0x400000)
DWORD SectionAlignment; // 内存中节区对齐粒度(通常0x1000)
DWORD FileAlignment; // 文件中节区对齐粒度(通常0x200)
