c++如何读取和修改可执行文件的PE头信息_IMAGE_NT_HEADERS解析【进阶】

轻明小哥_3350

轻明小哥_3350

2026-03-30

464人浏览

原创

安全读取 PE 文件的 _IMAGE_NT_HEADERS 需先验证 DOS 头魔数、用 e_lfanew 定位并校验偏移有效性;修改 ImageBase 后须重算校验和、处理 ASLR 与重定位;解析时必须按 Machine 和 SizeOfOptionalHeader 动态选择 32/64 位头结构,校验和计算需置零自身、16 位累加、奇数补零、二次折叠。

c++如何读取和修改可执行文件的pe头信息_image_nt_headers解析【进阶】

怎么安全读取 PE 文件的 _IMAGE_NT_HEADERS?

直接用 fread 读整个文件再强转指针是常见错误——PE 文件头部位置不固定,DOS Header 末尾的 e_lfanew 字段才是关键跳转点。跳错地址会导致读到垃圾数据,甚至程序崩溃。

  • 先用 fopen 以 "rb" 模式打开文件,避免文本模式换行符干扰
  • 读前 64 字节(足够覆盖 _IMAGE_DOS_HEADER),检查 e_magic 是否为 0x5A4D(即 "MZ")
  • 提取 e_lfanew 值,必须验证是否在文件范围内,否则可能越界读取
  • 再 fseek 到该偏移,读入 _IMAGE_NT_HEADERS(通常 248 字节,但实际长度取决于可选头大小)

示例关键判断:

if (e_lfanew  file_size - sizeof(IMAGE_NT_HEADERS)) { /<em> 无效 PE </em>/ }

修改 OptionalHeader.ImageBase 后为什么加载失败?

改了 ImageBase 却无法加载,大概率是因为没同步更新校验和、没重定位、或忽略了 ASLR 兼容性。Windows 加载器对校验和有严格校验逻辑,哪怕只是改一个字节,也得重新计算。

  • 修改前先调用 CheckSumMappedFile(Windows SDK 提供)或手动实现校验和算法(RFC 1071 标准)
  • 若目标文件启用了 ASLR(DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE),改 ImageBase 可能被忽略,加载器仍会随机基址重定位
  • 修改后必须用 SetFilePointer + WriteFile 精确写回原位置,不能只写结构体——PE 头部前后都有其他字段,写错长度会破坏后续节表

注意:修改 ImageBase 不等于绕过 DEP/ASLR,它只是告诉加载器“首选基址”,现代系统下作用有限。

用 IMAGE_OPTIONAL_HEADER64 解析 32 位文件会怎样?

会解析出完全错误的字段布局,比如把 32 位的 AddressOfEntryPoint 当成高位 32 位,导致入口点地址变成 0 或极大值,调试器直接跳飞。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 必须通过 NT_HEADERS.FileHeader.Machine 判断架构:IMAGE_FILE_MACHINE_I386 对应 32 位,IMAGE_FILE_MACHINE_AMD64 对应 64 位
  • OptionalHeader 的大小由 NT_HEADERS.FileHeader.SizeOfOptionalHeader 决定,不是硬编码;32 位通常是 224 字节,64 位是 240 字节
  • 手动解析时别依赖 sizeof(IMAGE_OPTIONAL_HEADER64),它在 32 位编译环境下也可能被定义,但内容不对

一个典型坑:SizeOfStackReserve 在 32 位头里偏移是 0x40,在 64 位头里是 0x50——偏移错了,后面全错。

PE 头修改后校验和不匹配,自己算容易漏什么?

自己实现校验和最常漏的是:跳过校验和字段本身、没按 16 位无符号整数累加、没处理奇数字节数、没做最终折叠(两次求和)。Windows 的 CheckSumMappedFile 实际做了两轮累加,且把校验和字段临时置零再算。

  • 计算前,先将当前校验和字段(OptionalHeader.CheckSum)设为 0,否则会把自己也算进去
  • 按每 2 字节为单位解释内存,累加为 DWORD,溢出不丢弃(即带进位加)
  • 若总字节数为奇数,最后一个字节按低位补 0 构成 16 位再加(不是忽略)
  • 最终结果要再做一次“高 16 位 + 低 16 位”,直到结果落在 16 位内,然后加上原始和的低 16 位

这一步看似机械,但少一个细节,生成的校验和就通不过 LoadLibrary 验证。

PE 头解析不是纯结构体 memcpy 能搞定的事,每个字段背后都连着加载器的一条路径。改得越多,越要确认你动的是加载器真正在意的那个值,而不是你以为它在意的。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

2025.06.09

5174

18

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

2025.07.04

5351

25

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

379

31

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.26

3399

3

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.27

2938

6

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

2023.08.01

1528

3

windows查看端口被占用的情况
windows查看端口被占用的情况

windows查看端口被占用的情况的方法:1、使用Windows自带的资源监视器;2、使用命令提示符查看端口信息;3、使用任务管理器查看占用端口的进程。本专题为大家提供windows查看端口被占用的情况的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2679

5

windows无法访问共享电脑
windows无法访问共享电脑

在现代社会中,共享电脑是办公室和家庭的重要组成部分。然而,有时我们可能会遇到Windows无法访问共享电脑的问题。这个问题可能会导致数据无法共享,影响工作和生活的正常进行。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.08

3350

4

windows自动更新
windows自动更新

Windows操作系统的自动更新功能可以确保系统及时获取最新的补丁和安全更新,以提高系统的稳定性和安全性。然而,有时候我们可能希望暂时或永久地关闭Windows的自动更新功能。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

1697

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习