PE文件的分析和构造超详细过程

本文详细讲述如何从0构造一个PE文件,运行该文件会弹出一个HelloPE的窗口

目录

预备知识

1. 构造DOS头IMAGE_DOS_HEADER

1.1 构造DOS_MZ头 

1.2 构造DOS_STUB 

2、构造PE头IMAGE_NT_HEADERS  248字节

2.1 signature 

2.2 IMAGE_FILE_HEADER 

2.3 IMAGE_OPTION_HEADER   

 3、构造段表   

4、构造每个段的实际内容  

4.1 构造.text段

4.2 构造.rdata段

4.3 构造.data段

5、修改前面待确定的地址

5.1 修改SizeOfCode、AddressOfEntryPoint、BaseOfCode

5.2 修改DataDirectory的第2项和第13项

5.3 修改call指令对应的两个函数地址

6、运行程序


预备知识

FOV、RVA、VA概念及转换

FOA(File Offset Address):和内存无关,它是指某个位置距离文件头的偏移,在内存图中实际显示的地址即行加列就是FOA

RVA(Relative Virual Address): PE文件的相对虚拟地址是PE文件中数据相对PE文件装载到内存后到基址的距离。例如PE文件装入虚拟地址(VA)空间的400000h处,且进程从虚址401000h开始执行,该进程的RVA 为1000h

VA(Virtual Address): 虚拟内存地址,PE文件被操作系统加载进内存后的地址,计算公式为:VA= RVA+ ImageBase

以下位置的行+列=FOA=00 00 04 00 + 00 00 00 04 = 00 00 04 04

得到FOA=404h再计算RVA和VA,假设程序在文件中对齐粒度为200h,映射到内存对齐粒度是1000h,.date、.rdate、.text映射到内存中每段需要补800h的0字节,基地址假设为00 40 00 00

上图左侧是原文件,右侧是映射到内存

本实验DOS头加PE头加块表544字节,占220h,220h对齐需要2个200h,所以DOS头加PE头加块表一共400h,属于①的情况

即FOA=404H,RVA=1004h,VA=401004h

还有一种情况FOA<DOS头+PE头+块表,这个时候映射过去RVA=FOA

PE文件结构图如下

1. 构造DOS头IMAGE_DOS_HEADER

由DOS_MZ头和DOS_STUB两部分组成

1.1 构造DOS_MZ头 

e_magic:标记是否是可执行文件,所有PE都要用“MZ”开头,对应4D 5A,填入DOS_MZ的最前面2个字节

填充58个字节0

e_lfanew:PE头相对于DOS头的偏移,由于DOS_STUB大小不固定,所以用该值定位PE头的位置,在DOS_MZ的最后面4个字节

1.2 构造DOS_STUB 

表示指令字节码,可以全填0

完整DOS头如图所示,其中e_lfanew为B0 00 00 00,真实值是反过来也就是00 00 00 B0,DOS开始位置是00 00 00 00,所以PE头的位置是

00 00 00 00+00 00 00 B0=00 00 00 B0,即PE头从00 00 00 B0开始

2、构造PE头IMAGE_NT_HEADERS  248字节

由signature、IMAGE_FILE_HEADER、IMAGE_OPTION_HEADER三部分组成

2.1 signature 

标志值为PE00,所以填入50 45 00 00

2.2 IMAGE_FILE_HEADER 

Machine:PE运行的CPU,Intel平台是01 4C,反过来填入4C 01 ,

NumberOfSections:PE文件段的总数,一共有三个(.text,.rdate,.date),所以值为00 03,反过来填入03 00

填充12字节0

SizeOfOptionalHeader:表示后面IMAGE_OPTION_HEADER的大小,为224字节,224是00 E0,反过来填入E0 00

Characteristics:成员二进制值0000 0001 0000 1111,即01 0F,填入0F 01

2.3 IMAGE_OPTION_HEADER   

Magic:文件格式 01 0B表示.exe文件,01 07表示ROM映像,所以填入0B 01

链接程序主版本号和次版本号,各占1字节,初始化为00 00

Sizeofcode:可执行代码对齐后的长度,即.text段对齐后的长度,后面才知道,先填入AA AA AA AA,本实验是200h,即填入00 02 00 00

SizeofInitializedDate:已初始化节的总大小,填入00 00 00 00

SizeofUnitializedDate:未初始化节的总大小,填入00 00 00 00

AddressOfEntryPoint:代码入口的RVA地址,程序的主函数或入口点的地址。这个地址并不一定是代码段.text的起始位置,因为程序可能包含一些初始化代码,后面才知道,先填入AA AA AA AA本实验是1000h,即填入00 10 00 00

BaseOfCode:.text段的RVA地址,后面才知道,先填入AA AA AA AA,本实验是1000h,即填入00 10 00 00

BaseofDate:.data段的起始RVA,先填入00 00 00 00,本实验是3000h,即填入00 30 00 00

ImageBase:映像基址00 40 00 00,反过来填入00 00 40 00

SectionAlignment:内存字段对齐粒度1000h,00 00 10 00,反过来填入

00 10 00 00

FileAlignment:文件节对齐粒度200h,即00 00 02 00,反过来填入00 02 00 00

操作系统的主版本号、次版本号各2字节,填入00 00 00 00

PE的主版本号、次版本号各2字节,填入00 00 00 00

子系统的主版本号、次版本号各2字节,填入00 00 00 00

Win32version:未使用,填入00 00 00 00

SizeOfImage:映射对齐后占内存的大小:1000h+3*1000h=4000h,即00 00 40 00,反过来填入00 40 00 00

SizeOfHeader:文件所有文件头的长度和

DOS_MZ:64字节

DOS_STUB:不固定,本实验是112字节

Signature:4字节

IMAGE_OPTION_HEADER:224字节

3个段表头每个段表头40,3*40=120

64+112+4+224+120=544,十六进制02 20,由于对齐粒度是200h,所以对齐需要两个200h,即400h,00 00 04 00,反过来填入00 04 00 00

Checksum:校验和,填入00 00 00 00

Subsystem:windows图形程序,值为2,即00 02,反过来填入02 00

Dllcharacteristics:DDL文件特性,填入00 00

SizeOfStackReserver:初始化时的栈大小,填入00 00 00 00

SizeOfStackCommit:初始化时实际提交的栈大小,填入00 00 00 00

SizeOfHeapReserver:初始化时的堆大小,填入00 00 00 00

SizeOfHeapCommit:初始化时实际提交的堆大小,填入00 00 00 00

LoaderFlags:与调试有关,默认为0,填入00 00 00 00

NumberOfRvaAndSizes:DateDirectory项目数量,通常为16个,即10h,填入10 00 00 00

DateDirectory:包含16个元素,每个元素8个字节,第2个元素是IT(导入表)的RVA和大小各4字节,第13个元素是IAT(导入函数地址)的RVA和大小各4字节,都先填为AA AA AA AA AA AA AA AA

最后DOS头加PE头如下

PE头从 00 B0开始

IMAGE_OPTIONAL_HEADER32从00 C8开始

数据目录表从01 28开始

 3、构造段表   

段表由4个段头部组成,有三个段(.text,.data,.edata),每个段都有一个段头部对应,所以有3个段头部,最后还要1个空的段头部,总共4 个,每个段头部40字节, 所以段表一共160字节

3.1 构造.text段表

Name:表示段名称,.text对应2E 74 65 78 74 00 00 00,名称不用反写直接填

VirtuaSize:不确定,先填入AA AA AA AA

VirtualAddress:1000h,对应00 00 10 00,填入00 10 00 00

SizeOfRawData:用一个对齐粒度200h,对应00 00 02 00,填入00 02 00 00

PointerToRawData:400h,对应00 00 04 00,填入00 04 00 00

PointerToRelocation:填入00 00 00 00

PointerToLinenumbers:填入00 00 00 00

NumberOfRelocations:填入00 00

NumberOfRelocations:填入00 00

Charayeristics:填入60 00 00 20

3.2 构造.rdata段表

Name:表示段名称,.rdata对应2E 72 64 61 74 61 00 00 00,直接填入

VirtuaSize:不确定,先填入AA AA AA AA

VirtualAddress:2000h,对应00 00 20 00,填入00 20 00 00

SizeOfRawData:用一个对齐粒度200h,对应00 00 02 00,填入00 02 00 00

PointerToRawData:600h,对应00 00 06 00,填入00 06 00 00

PointerToRelocation:填入00 00 00 00

PointerToLinenumbers:填入00 00 00 00

NumberOfRelocations:填入00 00

NumberOfRelocations:填入00 00

Charayeristics:填入40 00 00 40

3.3 构造.data段表

Name:表示段名称,.rdata对应2E 64 61 74 61 00 00 00,直接填入

VirtuaSize:不确定,先填入AA AA AA AA

VirtualAddress:3000h,对应00 00 30 00,填入00 30 00 00

SizeOfRawData:用一个对齐粒度200h,对应00 00 02 00,填入00 02 00 00

PointerToRawData:800h,对应00 00 08 00,填入00 08 00 00

PointerToRelocation:填入00 00 00 00

PointerToLinenumbers:填入00 00 00 00

NumberOfRelocations:填入00 00

NumberOfRelocations:填入00 00

Charayeristics:填入40 00 00 C0

然后再补40字节的0,最后段表如下

块表从01 A8开始

.text块从04 00开始

.rdata块从06 00开始

.data块从08 00开始

DOS头加PE头加段表最后如下

现在一共240h,由于要对齐400h,所以补充0到400h

4、构造每个段的实际内容  

4.1 构造.text段

汇编代码为

6A 00                      push 0                       ;第一个消息框风格(0表示默认风格)

68 00304000       push 0x403000          ;标题字符串所在的地址

68 07304000       push 0x403007           ;内容字符串所在的地址

6A 00                  push 0                         ;消息框所属窗口句柄

FF 15 ????          call ptr[????]                     ;调用MessageBoxA

6A 00                  push 0                         ;ExitProcess函数的参数,程序退出码

FF 15 ????          call ptr[????]             ;调用ExitProcess

call后面地址不确定,先填AA AA AA AA

不算0实际长度只有28字节,即1Bh,在.text段表的VirtualSize从AA  AA  AA  AA改成 1B 00 00 00

最后补齐200h,.text段最后如下

4.2 构造.rdata段

图中相同颜色表示对应关系,例如54 20 00 00指向5C 20 00 00然后指向9D 01 4D 65 73 73 61 67 65 42 6F 78 41

76 20 00 00是DDL1(kernel32.dll)的函数ExitProcess的地址,然后隔4字节0,5C 20 00 00 的DDL2(user32.dll)的函数MessageBoxA的地址,然后隔4字节0

两个导入表描述符

54 20 00 00 00 00 00 00 00 00 00 00 6A 20 00 00 08 20 00 00

4C 20 00 00 00 00 00 00 00 00 00 00 84 20 00 00 00 20 00 00

先分析第一个导入表描述符

54 20 00 00 00 00 00 00 00 00 00 00 6A 20 00 00 08 20 00 00

54 20 00 00即2054,转换成FOA为0654,这个位置对应5C 20 00 00,即205C,再转换成FOA为065C,这个位置对应9D 01…,即指向MessageBoxA函数的开头。6A 20 00 00即206A,转换成FOA为066A,这个位置对应75 73…,即指向user32.dll的开头。08 20 00 00即2008,为user32.dll的RVA

分析第二个导入表描述符

4C 20 00 00 00 00 00 00 00 00 00 00 84 20 00 00 00 20 00 00

4C 20 00 00即204C,转换成FOA为064C,这个位置对应76 20 00 00,即2076,在转换成FOA为0676,这个位置对应80 00 45 78…,即ExitProcess函数的开头。84 20 00 00即2084,转换成FOA为0684,这个位置对应6B 65 72 6E…,即kernel32.dll。00 20 00 00为kernel32.dll的RVA

长度有144字节,即8Fh,在.rdata段表的VirtualSize从AA  AA  AA  AA改成

8F 00 00 00

最后补齐200h,.rdata段最后如下

长度只有16字节,即0E,在.data段表的VirtualSize从AA  AA  AA  AA改成 0E 00 00 00

4.3 构造.data段

.data段设置的是弹出窗口的标题和字符串内容,标题设置为TestPE,内容为HelloPE

最后补齐200h,.data段最后如下

5、修改前面待确定的地址

因为当时很多地址不确定,全填了AA AA AA AA,所以现在返回修改

5.1 修改SizeOfCode、AddressOfEntryPoint、BaseOfCode

SizeOfCode是.text对齐后的长度,即200h,填入00 02 00 00

AddressOfEntryPoint是.text的RVA地址,即1000h,填入00 10 00 00

BaseOfCode是.text的FOA地址,即400h,填入00 02 00 00

修改前

修改后

5.2 修改DataDirectory的第2项和第13项

IAT的RVA为2000h,有多少个导入的DLL就有多少个IAT表项,每个表项有4字节的函数地址和4字节的0,本实验一共要用两个dll(user32.dll和Kernel32.dll),所以整个IAT大小为16字节,即10h,DataDirectory第13项填为00 20 00 00 10 00 00 00

IT的RVA为2010h,反写为10 20 00 00

导入表描述符20字节,一共2个函数加上一个空导入表描述符即60字节,3Ch,反写为3C 00 00 00

修改前

修改后

5.3 修改call指令对应的两个函数地址

两个函数RVA加上ImageBase结果分别为00 40 20 80和00 40 20 00,反过来填08 20 40 00和00 20 40 00

修改前

修改后

6、运行程序

把件后缀改成.exe,运行结果如下

使用LordPE软件查看结构

如果想要显示中文编码,例如你好PE,要使用GBK编码,“你好”的GBK编码是C4 E3 BA C3,所以把原来data段的48 65 6C 6C 6F改成C4 E3 BA C3,如下图

运行结果如下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/541078.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫:蝉妈妈返回参数data解密

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…

Spring Boot | Spring Boot 整合 “Servlet三大组件“ ( Servlet / Filter / Listene )

目录: Spring Boot 整合 "Servlet三大组件" &#xff1a;1. 使用 "组件注册" 的方式 "整合Servlet三大组件" ( 实际操作为 : 创建自定义的"三大组件"对象 结合刚创建"的自定义组件对象"来 将 XxxRegistrationBean对象 通过…

sparkSql join 关联机制

&#x1f490;&#x1f490;扫码关注公众号&#xff0c;回复 spark 关键字下载geekbang 原价 90 元 零基础入门 Spark 学习资料&#x1f490;&#x1f490; join 实现机制 Join 有 3 种实现机制&#xff0c;分别是 NLJ&#xff08;Nested Loop Join&#xff09;、SMJ&#xf…

【VUE】使用Vue和CSS动画创建滚动列表

使用Vue和CSS动画创建滚动列表 在这篇文章中&#xff0c;我们将探讨如何使用Vue.js和CSS动画创建一个动态且视觉上吸引人的滚动列表。这个列表将自动滚动显示项目&#xff0c;类似于轮播图的方式&#xff0c;非常适合用于仪表盘、排行榜或任何需要在有限空间内展示项目列表的应…

【Altium Designer 20 笔记】隐藏PCB上的信号线(连接线)

使用网络类隐藏特定类型的信号线 如果你想要隐藏特定类型的信号线&#xff08;例如电源类&#xff09;&#xff0c;你可以首先创建一个网络类。使用快捷键DC调出对象类浏览器&#xff0c;在Net Classes中右击添加类&#xff0c;并重命名&#xff08;例如为“Power”&#xff0…

【Qt 学习笔记】QWidget的geometry属性及window frame的影响

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ QWidget的geometry属性 文章编号&#xff1a;Qt 学习笔记 / 16 文章目…

spring boot学习第十七篇:OAuth2概述及使用GitHub登录第三方网站

0. 导言 我们在浏览器上可以访问成百上千个网站&#xff0c;使用每个网站的服务一般都要先注册账号&#xff0c;那么我们为了更好地记忆&#xff0c;一般都会在多个网站使用相同的账号和密码进行注册。那么问题就来了&#xff0c;如果在你注册的网站中有某些个网站的系统设计不…

C++进阶03 模板与群体数据

听课笔记简单整理&#xff0c;供小伙伴们参考~&#x1f95d;&#x1f95d; 第1版&#xff1a;听课的记录代码~&#x1f9e9;&#x1f9e9; 编辑&#xff1a;梅头脑&#x1f338; 审核&#xff1a;文心一言 目录 &#x1f433;课程来源 &#x1f40b;模板 &#x1f40b;8.…

小区烟火AI检测/楼道杂物堆积消防隐患AI智能识别方案

一、背景需求 据新闻报道&#xff0c;今年4月7日&#xff0c;安徽省合肥市肥东县一民房发生火灾&#xff0c;致1死11伤&#xff0c;起火点是“一楼楼道杂物间”。 因为小区居民楼楼道堆积大量杂物而导致的消防火灾事故也不在少数。楼道堆积杂物是一个长期存在的问题&#xff…

安装ODBC方法

1、运行 搜索 ODBC数据源管理程序 32位或者 64位 2、在用户DSN或者系统DSN选择添加&#xff08;建议前者&#xff09;&#xff0c;此处以添加access数据库的odbc驱动为例 3、安装成功

2024妈妈杯数学建模A 题思路分析-移动通信网络中 PCI 规划问题

# 1 赛题 A 题 移动通信网络中 PCI 规划问题 物理小区识别码(PCI)规划是移动通信网络中下行链路层上&#xff0c;对各覆盖 小区编号进行合理配置&#xff0c;以避免 PCI 冲突、 PCI 混淆以及 PCI 模 3 干扰等 现象。 PCI 规划对于减少物理层的小区间互相干扰(ICI)&#xff0c;增…

jenkins通过pipeline部署springboot项目

部署方案&#xff1a; 1、springboot项目不保存部署的pipeline或dockerfile构建脚本等与部署相关的问文件&#xff0c;业务项目只需关心业务&#xff0c;能够正常构建为jar包即可 2、新建一个代码仓库&#xff0c;用于保存项目需要构建的Jenkinsfile 3、jenkins配置pipeline地址…

Element ui 动态展示表格列,动态格式化表格列的值

需求 后台配置前端展示的表格列&#xff0c;遇到比如 文件大小这样的值&#xff0c;如果后台存的是纯数字&#xff0c;需要进行格式化展示&#xff0c;并且能控制显示的小数位数&#xff0c;再比如&#xff0c;部分列值需要加单位等信息&#xff0c;此外还有状态类&#xff0…

【心路历程】初次参加蓝桥杯实况

送给大家一句话&#xff1a; 寂静的光辉平铺的一刻&#xff0c;地上的每一个坎坷都被映照得灿烂。 – 史铁生 《我与地坛》 初次参加蓝桥杯有感 一点小小的震撼难评的做题过程A题 艺术与篮球问题描述解题 B 题 五子棋问题描述解题 C题 训练士兵问题描述解题 D题 团建解题 E题 …

基于SpringBoot+Vue的毕业设计管理系统(源码+文档+部署+讲解)

一.系统概述 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针…

【前端】layui table表格勾选事件,以及常见模块

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《前端》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 表格勾选事…

接口测试-Mock测试方法详解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、关于Mock测试 1、什么是Mock测试&#xff1f; Mock 测试就是在测试过程中&#xff0c;对于…

Vue3整合wangEditor(富文本编辑器框架) 以及提供存储渲染方案

目录 概述 Vue3整合wagnEditor 图片的上传 图片的删除 文章存储 文章渲染 概述 实现功能&#xff1a;管理端使用富文本编辑器编写文章内容&#xff0c;将编辑好的文章存入数据库或服务器中&#xff0c;前端应用读取存储的文章内容作展示。 本文章能提供 ①Vue3整合wangEdi…

一款免费、开源、可批量识别的离线OCR软件,适用于 Windows7 x64及以上平台

免费&#xff1a;本项目所有代码开源&#xff0c;完全免费。方便&#xff1a;解压即用&#xff0c;离线运行&#xff0c;无需网络。高效&#xff1a;自带高效率的离线OCR引擎&#xff0c;内置多种语言识别库。灵活&#xff1a;支持命令行、HTTP接口等外部调用方式。功能&#x…

Android开发——控件

目录 TextView 注意&#xff1a; ​编辑带阴影的textview&#xff1a;&#xff08;一般用于给字体添加属性&#xff09; ​编辑 跑马灯效果的textview​编辑 Button (前几个常用&#xff09; Botton事件处理 EditText (文本框&#xff09; 如何获取文本框里面的内容…