- 公开视频 -> 链接点击跳转公开课程
- 博客首页 -> 链接点击跳转博客主页
目录
[IMAGE_OPTIONAL_HEADER 概述](#IMAGE_OPTIONAL_HEADER 概述)
[IMAGE_OPTIONAL_HEADER 结构体字段详解](#IMAGE_OPTIONAL_HEADER 结构体字段详解)
IMAGE_OPTIONAL_HEADER 概述
作用
- 描述PE文件在内存中的布局和运行时的关键参数。
- 包含代码段、数据段、堆栈大小、入口地址、子系统类型等信息。
- 对于可执行文件(EXE)是必需的(尽管名为"Optional"),动态链接库(DLL)也包含此结构。
位置
- 位于PE头的第二部分,紧随 IMAGE_FILE_HEADER 之后。
- 在32位和64位系统中有不同版本:
- IMAGE_OPTIONAL_HEADER32(32位)
- IMAGE_OPTIONAL_HEADER64(64位)
IMAGE_OPTIONAL_HEADER 结构体字段详解
|------------------------------|--------|---------------------------------------------------------|----------------------|
| 字段名 | 大小(字节) | 描述 | 32/64位差异说明 |
| Magic | 2 | 标识文件类型:0x10B(32位PE),0x20B(64位PE) | 关键标志位 |
| MajorLinkerVersion | 1 | 链接器的主版本号 | 可自定义 |
| MinorLinkerVersion | 1 | 链接器的次版本号 | 可自定义 |
| SizeOfCode | 4 | 所有代码节的总大小(.text段等,按FileAlignment对齐后的值) | 仅统计可执行代码 |
| SizeOfInitializedData | 4 | 已初始化数据的节总大小(如.data、.rdata段) | 包含全局变量、常量等 |
| SizeOfUninitializedData | 4 | 未初始化数据的节总大小(.bss段,文件不存储,内存中用零填充) | 文件偏移为0 |
| AddressOfEntryPoint | 4 | 程序入口点RVA(指向main或DllMain,若为0则无入口) | 加壳程序会修改此值 |
| BaseOfCode | 4 | 代码段起始RVA(通常为.text段,64位PE中仍保留) | 64位中意义相同 |
| BaseOfData | 4 | 数据段起始RVA(仅32位PE有效,64位PE中此字段被移除) | 64位无此字段 |
| ImageBase | 4/8 | 首选加载基址(32位为4字节,64位为8字节,默认EXE=0x00400000,DLL=0x10000000) | 受ASLR影响实际基址可能不同 |
| SectionAlignment | 4 | 内存中节的对齐粒度(通常为0x1000即4KB) | 必须≥FileAlignment |
| FileAlignment | 4 | 文件中节的对齐粒度(通常为0x200即512字节,或0x1000) | 文件尺寸优化关键 |
| MajorOperatingSystemVersion | 2 | 要求的最低操作系统主版本号(如Windows 10=10) | 影响加载行为 |
| MinorOperatingSystemVersion | 2 | 要求的最低操作系统次版本号 | 通常为0 |
| MajorImageVersion | 2 | 映像文件的主版本号(由开发者定义,如程序版本号) | 补充字段 |
| MinorImageVersion | 2 | 映像文件的次版本号 | 补充字段 |
| MajorSubsystemVersion | 2 | 子系统主版本号(如GUI程序需≥4.0) | 兼容性关键 |
| MinorSubsystemVersion | 2 | 子系统次版本号 | 通常为0 |
| Win32VersionValue | 4 | 保留字段,必须为0 | 补充字段 |
| SizeOfImage | 4 | 映像加载到内存后的总大小(按SectionAlignment对齐) | 必须准确否则加载失败 |
| SizeOfHeaders | 4 | 所有头结构(DOS头+PE头+节表)的总大小(按FileAlignment对齐) | 包含节表结束后的填充字节 |
| CheckSum | 4 | 文件校验和(用于驱动、系统DLL,EXE可选,工具可生成)CheckSumMappedFile | 补充用途说明 IMAGEHlP.DLL |
| Subsystem | 2 | 子系统类型 | l决定是否显示控制台窗口 |
| DllCharacteristics | 2 | DLL属性标志 | 补充标志位细节 |
| SizeOfStackReserve | 4/8 | 初始保留的栈大小(32位为4字节,64位为8字节,默认1MB) | 栈溢出防护相关 |
| SizeOfStackCommit | 4/8 | 初始提交的栈大小(32位为4字节,64位为8字节,默认4KB) | 动态扩展栈空间 |
| SizeOfHeapReserve | 4/8 | 初始保留的堆大小(32位为4字节,64位为8字节,默认1MB) | 堆管理相关 |
| SizeOfHeapCommit | 4/8 | 初始提交的堆大小(32位为4字节,64位为8字节,默认4KB) | 动态扩展堆空间 |
| LoaderFlags | 4 | 加载标志 | 补充用途说明 |
| NumberOfRvaAndSizes | 4 | 数据目录项数量(固定为16) | 必须一致 |
| DataDirectory | 16×8 | 数据目录数组,每个条目包含VirtualAddress(RVA)和Size | |
数据目录(DataDirectory)
数据目录是 IMAGE_OPTIONAL_HEADER 的最后一部分,包含16个条目,每个条目由两个字段组成:
- VirtualAddress:数据结构的RVA地址
- Size:数据结构的大小
|-----|------------------------------|------------------------------------|
| 索引 | 名称 | 用途描述 |
| 0 | 导出表(Export Table) | 存储DLL导出函数的名称、序号及地址,供外部程序动态链接。 |
| 1 | 导入表(Import Table) | 记录程序依赖的DLL及导入函数信息,加载时填充IAT(导入地址表)。 |
| 2 | 资源表(Resource Table) | 存储程序的图标、字符串、版本信息、对话框等资源。 |
| 3 | 异常表(Exception Table) | 包含结构化异常处理(SEH)。 |
| 4 | 安全目录(Security Directory) | 存储数字签名、证书等安全信息(独立于资源表,用于文件完整性验证)。 |
| 5 | 重定位表(Relocation Table) | 处理基址重定位(ASLR启用时调整内存地址)。 |
| 6 | 调试信息(Debug Directory) | 调试符号、时间戳及PDB文件路径(调试版本存在)。 |
| 7 | 架构特定数据(Architecture) | 保留字段,通常为0(历史遗留,未实际使用)。 |
| 8 | 全局指针(Global Ptr) | RISC架构中用于全局寄存器优化。 |
| 9 | TLS表(Thread Local Storage) | 定义线程本地存储数据。 |
| 10 | 加载配置表(Load Config) | 安全特性配置(如SEH合法性检查、控制流防护CFG)。 |
| 11 | 绑定导入表(Bound Import) | 预绑定DLL地址以加速加载。 |
| 12 | IAT(Import Address Table) | 导入函数的实际内存地址表,加载时由系统填充。 |
| 13 | 延迟导入(Delay Import) | 延迟加载的DLL信息。 |
| 14 | CLR运行时头(COM Descriptor) | 与 .NET 程序相关的 CLR(公共语言运行时)头信息。 |
| 15 | 保留(Reserved) | 未使用,必须为0。 |