当前位置: 首页 > news >正文

PE之不同区域的结构体定义

 

 

 

 

 

PE之不同区域的结构体定义
1)PE文件不同区域的结构体各有其用:DOS头(_IMAGE_DOS_HEADER)标识DOS兼容性并定位PE头;PE头(_IMAGE_NT_HEADERS)含文件头和可选头,定整体信息;节表(_IMAGE_SECTION_HEADER)描述代码/数据节;有文件头、可选头、数据目录表及导出表、导入表、重定位表等,分工处理架构、加载配置、功能结构定位及函数导入导出、地址修正,共同构成 PE 结构框架。


2)DOS头:IMAGE_DOS_HEADER
DOS头是 PE文件的第一个区域,用于标识文件为DOS可执行格式(.EXE),结构定义如下:
typedef struct _IMAGE_DOS_HEADER {
WORD   e_magic;        // DOS签名,固定为"0x5A4D"(即ASCII的"MZ")
WORD   e_cblp;         // 最后一个块的字节数
WORD   e_cp;           // 文件占用的块数
WORD   e_crlc;         // 重定位表项数
WORD   e_cparhdr;      // 头部大小(以段落为单位)
WORD   e_minalloc;     // 所需的最小额外内存(段落)
WORD   e_maxalloc;     // 所需的最大额外内存(段落)
WORD   e_ss;           // 初始SS值(相对偏移)
WORD   e_sp;           // 初始SP值
WORD   e_csum;         // 校验和
WORD   e_ip;           // 初始IP值
WORD   e_cs;           // 初始CS值(相对偏移)
WORD   e_lfarlc;       // 重定位表的偏移量
WORD   e_ovno;         // 覆盖号
WORD   e_res[4];       // 保留字段(4个WORD)
WORD   e_oemid;        // OEM标识符
WORD   e_oeminfo;      // OEM信息
WORD   e_res2[10];     // 保留字段(10个WORD)
LONG   e_lfanew;       // PE头的偏移量(关键字段,指向真正的PE结构)
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
核心作用:通过e_magic标识DOS兼容性,通过e_lfanew指向PE文件的真正头部(_IMAGE_NT_HEADERS)。


3)PE头:IMAGE_NT_HEADERS
PE头是PE文件的核心区域,包含文件的整体信息,定义如下:
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;               // PE签名,固定为"0x00004550"(即"PE\0\0")
IMAGE_FILE_HEADER FileHeader;  // 文件头(基本属性)
IMAGE_OPTIONAL_HEADER32 OptionalHeader;  // 可选头(32位)
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

// 64位版本(OptionalHeader结构不同)
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;  // 64位可选头
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
结构体中字段说明:
Signature:确认文件为PE格式。
FileHeader:包含文件类型(如 EXE/DLL)、节表数量、时间戳等基础信息。
OptionalHeader:包含更详细的加载信息(如入口点地址、内存映射基址、节表偏移等)。


4)节表:IMAGE_SECTION_HEADER
节表由多个节头组成,每个节头描述PE文件中的一个 "节"(如.text代码节、.data数据节等),定义如下:
typedef struct _IMAGE_SECTION_HEADER {
BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];  // 节名(8字节,如".text\0")
union {
DWORD   PhysicalAddress;  // 物理地址(与VirtualSize含义相同)
DWORD   VirtualSize;      // 节在内存中的大小(未对齐)
} Misc;
DWORD   VirtualAddress;       // 节在内存中的起始地址(相对基址)
DWORD   SizeOfRawData;        // 节在磁盘上的大小(对齐后)
DWORD   PointerToRawData;     // 节在磁盘上的偏移量
DWORD   PointerToRelocations; // 重定位信息偏移(OBJ文件用)
DWORD   PointerToLinenumbers; // 行号信息偏移
WORD    NumberOfRelocations;  // 重定位项数
WORD    NumberOfLinenumbers;  // 行号项数
DWORD   Characteristics;      // 节属性(如可读、可写、可执行)
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
每个节对应文件中一段连续的数据,通过节表可以定位节在磁盘和内存中的位置及属性。
这些结构体是解析PE文件格式的基础,从DOS头过渡到PE头,再通过节表定位具体内容,共同构成了 PE 文件的结构框架。如果需要更深入了解某部分细节(如可选头字段、节属性等),可以进一步补充说明。


5)文件头:IMAGE_FILE_HEADER(PE头的子结构)  
IMAGE_FILE_HEADER是PE头(_IMAGE_NT_HEADERS)的核心子结构,存储文件的基础属性,定义如下:  
typedef struct _IMAGE_FILE_HEADER {
WORD    Machine;               // 目标机器架构(如0x8664表示x64,0x014C表示x86)
WORD    NumberOfSections;      // 节表数量(决定节头的总个数)
DWORD   TimeDateStamp;         // 文件创建时间戳(从1970年1月1日起的秒数)
DWORD   PointerToSymbolTable;  // 符号表偏移(调试用,通常为0)
DWORD   NumberOfSymbols;       // 符号数量(调试用,通常为0)
WORD    SizeOfOptionalHeader;  // 可选头大小(32位为0xE0,64位为0xF0)
WORD    Characteristics;       // 文件属性(如0x0002表示可执行,0x2000表示DLL)
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;  
核心作用:定义文件的架构、节数量、类型(EXE/DLL)等基础元信息,是解析节表和可选头的前提。


6)可选头:IMAGE_OPTIONAL_HEADER(PE头的子结构)  
可选头是PE加载的核心配置区,32位和64位结构类似(差异用注释标注),定义如下:  
typedef struct _IMAGE_OPTIONAL_HEADER32 {
WORD    Magic;                     // 标识位数(0x10B=32位,0x20B=64位)
BYTE    MajorLinkerVersion;        // 链接器主版本
BYTE    MinorLinkerVersion;        // 链接器次版本
DWORD   SizeOfCode;                // 代码节总大小(磁盘上)
DWORD   SizeOfInitializedData;     // 已初始化数据总大小
DWORD   SizeOfUninitializedData;   // 未初始化数据总大小
DWORD   AddressOfEntryPoint;       // 程序入口点(内存中的RVA)
DWORD   BaseOfCode;                // 代码节起始RVA(32位特有)
DWORD   BaseOfData;                // 数据节起始RVA(32位特有)
DWORD   ImageBase;                 // 首选加载基址(32位:0x00400000常见;64位:0x0000000140000000)
DWORD   SectionAlignment;          // 内存中节对齐粒度(通常为0x1000)
DWORD   FileAlignment;             // 磁盘中节对齐粒度(通常为0x200)
WORD    MajorOperatingSystemVersion; // 目标系统主版本
WORD    MinorOperatingSystemVersion; // 目标系统次版本
WORD    MajorImageVersion;         // 镜像主版本
WORD    MinorImageVersion;         // 镜像次版本
WORD    MajorSubsystemVersion;     // 子系统主版本
WORD    MinorSubsystemVersion;     // 子系统次版本
DWORD   Win32VersionValue;         // 保留(通常为0)
DWORD   SizeOfImage;               // 内存中总大小(对齐后)
DWORD   SizeOfHeaders;             // 所有头部总大小(对齐后)
DWORD   CheckSum;                  // 校验和(系统文件常用)
WORD    Subsystem;                 // 运行子系统(如0x02=Windows GUI,0x03=Windows CUI)
WORD    DllCharacteristics;        // DLL属性(如0x0040=动态基址)
DWORD   SizeOfStackReserve;        // 栈保留大小
DWORD   SizeOfStackCommit;         // 栈提交大小
DWORD   SizeOfHeapReserve;         // 堆保留大小
DWORD   SizeOfHeapCommit;          // 堆提交大小
DWORD   LoaderFlags;               // 加载标志(已废弃,为0)
DWORD   NumberOfRvaAndSizes;       // 数据目录表项数(固定为0x10)
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 数据目录表(16项)
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;  

// 64位差异:无BaseOfData,ImageBase为QWORD,SizeOfStackReserve等为QWORD
typedef struct _IMAGE_OPTIONAL_HEADER64 {
// ... 前半部分同32位(无BaseOfData)
QWORD   ImageBase;                 // 64位基址(QWORD)
// ... 中间字段同32位
QWORD   SizeOfStackReserve;        // 64位栈保留(QWORD)
// ... 其余同32位
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;  

核心作用:通过`AddressOfEntryPoint`定义程序入口,`ImageBase`指定加载基址,`DataDirectory`定位导入表、导出表等关键结构,是PE加载器的核心配置依据。


7)数据目录表项:IMAGE_DATA_DIRECTORY(可选头的子结构)  
数据目录表是可选头的最后一个字段,共16项,每项指向一个特定功能结构(如导入表、资源表),定义如下:  
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD   VirtualAddress;   // 结构在内存中的RVA(相对虚拟地址)
DWORD   Size;             // 结构大小(字节)
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;  

常见表项含义(通过索引区分):  
- 0:导出表(IMAGE_EXPORT_DIRECTORY)  
- 1:导入表(IMAGE_IMPORT_DESCRIPTOR)  
- 2:资源表(IMAGE_RESOURCE_DIRECTORY)  
- 5:重定位表(IMAGE_BASE_RELOCATION)  
- 6:调试信息(IMAGE_DEBUG_DIRECTORY)  
核心作用:作为“索引目录”,让加载器快速定位PE文件中的功能结构(如通过索引1找到导入表位置)。


8)导出表:IMAGE_EXPORT_DIRECTORY(用于DLL导出函数)  
导出表存储DLL对外暴露的函数信息,定义如下:  
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD   Characteristics;       // 保留(为0)
DWORD   TimeDateStamp;         // 导出表创建时间戳
WORD    MajorVersion;          // 主版本
WORD    MinorVersion;          // 次版本
DWORD   Name;                  // 模块名称的RVA(如"DLL名称"字符串)
DWORD   Base;                  // 导出函数起始序号(用于序号导出)
DWORD   NumberOfFunctions;     // 导出函数总数
DWORD   NumberOfNames;         // 按名称导出的函数数
DWORD   AddressOfFunctions;    // 函数地址表RVA(存储每个函数的RVA)
DWORD   AddressOfNames;        // 函数名称表RVA(存储函数名的RVA)
DWORD   AddressOfNameOrdinals; // 名称序号表RVA(关联名称与函数地址表索引)
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;  
核心作用:让其他程序通过函数名或序号调用DLL中的函数(如`kernel32.dll`导出`CreateFileA`)。


9)导入表:IMAGE_IMPORT_DESCRIPTOR(用于导入外部DLL函数)  
导入表描述程序依赖的外部DLL及函数,定义如下:  
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD   Characteristics;   // 0(废弃)
DWORD   OriginalFirstThunk; // 导入名称表(INT)RVA(存储函数名/序号)
} DUMMYUNIONNAME;
DWORD   TimeDateStamp;         // 导入时间戳(0表示未绑定)
DWORD   ForwarderChain;        // 转发链(通常为0)
DWORD   Name;                  // DLL名称的RVA(如"user32.dll")
DWORD   FirstThunk;            // 导入地址表(IAT)RVA(加载时填充函数实际地址)
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;  
核心作用:记录程序需要从外部DLL导入的函数,加载时由系统填充函数实际地址(如EXE导入`printf`来自`msvcrt.dll`)。


10)重定位表:IMAGE_BASE_RELOCATION(解决基址冲突)  
当PE文件加载地址与`ImageBase`不同时,需通过重定位表修正内存地址,定义如下:  
typedef struct _IMAGE_BASE_RELOCATION {
DWORD   VirtualAddress;   // 重定位块的起始RVA
DWORD   SizeOfBlock;      // 重定位块总大小(包括本结构)
// WORD    TypeOffset[1];  // 重定位项(实际数量=(SizeOfBlock-8)/2)
} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;  
每个重定位项(TypeOffset)是16位值:高4位为类型(0x3=IMAGE_REL_BASED_HIGHLOW,最常见),低12位为相对于VirtualAddress的偏移。  
核心作用:修正内存中依赖基址的地址(如全局变量指针、函数调用地址),确保程序在非首选基址加载时正常运行。

完整框架:DOS头定位PE头,PE头通过可选头的数据目录表定位导出表、导入表等功能结构,节表则对应实际的代码/数据存储区,最终实现程序的加载与执行。

http://www.dtcms.com/a/541682.html

相关文章:

  • Ubuntu24.04 赋予 Qt 应用程序 修改系统时间 权限
  • 50+孙悦梓潼舞台状态惊艳全网!自律的女神,连下颌线都是顶配
  • Rust:复合类型内存布局
  • net网站是国际域名吗wordpress发布文章页面错误
  • 英语学习 第一周 重难点
  • 做国际网站的流程unity做网站
  • 模板性公司网站图片网站制作的发展趋势
  • 石英加速度计如何敏锐感知飞机爬升与转弯的细微变化?
  • 【VS2019配置Boost】vs2019无法识别boost库目录
  • 要进一步增强门户网站建设合力有几个网站能在百度做推广
  • 常德网站建设常德做用户运营应该关注哪些网站
  • 目前做的最好的招聘网站外贸网站建设谷歌推广
  • 有空间与域名 怎么做网站为什么自己做的网站别的电脑打不开
  • 【AI大模型应用宝典60题】31-35
  • 03-Machine-5-fpioa.py K230 IO引脚复用功能演示
  • 郑州哪里培训网站建设优化好一点庆阳环境包装设计
  • 网站建设工作自策划实施以来网站开发实例社区
  • AI未来--零售行业“AI赋能,价值提升”
  • 京东网站建设策划书项目管理软件哪个好
  • 小程序中获取元素节点
  • 山东省聊城建设学校网站《网站开发实践》 实训报告
  • Android Service 的一个细节
  • 【QT】QTimer定时器读取寄存器的值
  • 2025年Java 面试题汇总(含答案解析)
  • 2025年--Lc221--144. 二叉树的前序遍历(递归版)-Java版
  • 生成式AI辅助教学设计的实践探索:从教案生成到教学评价的全流程优化
  • 做网站小程序挣钱吗互联网定制网站
  • 【场景题】List集合去重
  • 最小 k 个数
  • 镇江建网站佛山市城乡住房建设局网站首页