可移植可执行文件(PE)是 Windows 以及 UEFI PE/COFF 映像使用的可执行映像格式。 与 ELF 不同,PE 没有程序头表。加载器根据 COFF 头、可选头、节表和数据目录映射映像。
文件布局 #
PE 映像以 DOS 头(MZ)开头。其 e_lfanew 成员指向 NT 头,NT 头以 PE\0\0
签名开头。DOS 存根位于 DOS 头之后;某些工具链还会在 NT 头之前生成非标准的 Rich 头。
NT 头包含 COFF 文件头;对于可执行映像和 DLL,还包含可选头。COFF 头记录目标机器、 节数量、时间戳、符号表位置(最终映像中通常未使用)、可选头大小,以及可执行映像或 DLL 等特征。可重定位的 COFF 目标文件没有可选头。
可选头和寻址 #
PE32 可选头为 224 字节,PE32+ 头为 240 字节。PE32+ 使用 64 位地址字段,并省略
BaseOfData。Magic 标识 PE32(0x10b)、PE32+(0x20b)或 ROM 映像
(0x107)。
RVA(相对虚拟地址)是相对于映像基址的偏移量。运行时,虚拟地址为
ImageBase + RVA;首选 ImageBase 只是一个请求,基址重定位记录允许加载器将启用
ASLR 的映像映射到其他位置。AddressOfEntryPoint 和 BaseOfCode 都是 RVA。
BaseOfCode 标识映像中的第一个代码字节;它并不保证所有可执行代码都是连续的。
FileAlignment 控制节在磁盘上的对齐,而 SectionAlignment 控制节在内存中的对齐,
通常至少同样大。SizeOfHeaders 覆盖所有头以及节数据之前的填充,SizeOfImage
表示内存中按对齐计算的范围。Subsystem 选择所需环境,例如 Windows GUI、控制台或
EFI 引导服务驱动程序。数据目录指向导入、导出、资源、异常、证书、基址重定位、调试
信息、TLS 及其他加载器功能对应的表。
节 #
每个节头都会将一段文件数据映射到一段虚拟内存,并为其标记可读、可写、可执行、已初始化
数据或未初始化数据等特征。常见名称包括 .text、.rdata、.data、.pdata 和
.reloc,但名称属于约定,而不是加载器要求。VirtualSize 可能大于
SizeOfRawData;加载器会将剩余部分填充为零,未初始化数据正是这样表示的。
评论
在 GitHub 上阅读或评论(发表评论需要登录)