PE文件结构

如果想在我的平台上运行程序,你的文件就必须按照我所规定的格式组织

一.PE文件结构

1.可执行文件

  • 定义:可以由操作系统进行加载执行的文件
  • 格式:
windows平台PE(Portable Executable)文件结构
Linux平台ELF(Executable and Linking Format)文件结构

2.如何识别PE文件
<1>PE文件的特征指纹(PE指纹)
分别打开.exe.dll.sys等文件,观察特征前2个字节
<2>不要仅仅通过文件的后缀名来认定PE文件
3.PE的结构
PE文件的结果
各部分固定长度32位PE

二.PE文件的两种状态

这里对pe文件结构有个整体的把握


DOS头(DOS MZ+DOS块)
PE文件头(PE标示(4个字节)+ 标准PE头+ 扩展PE头)
节表
节数据


在节表的后半部分,以及节数据要实现文本对齐(这里是用空间换时间思想),导致的结果:节表的后半部分和节数据之间是松散的,其余部分是紧密连接在一起

三个标志位
整个DOS头的大小
前三部分整体大小(文本对齐后)
文本对齐的参数(硬盘+内存)
三个标志位结合各部分的固定长度,可推算出PE整体结构

两种状态:在硬盘中和在内存中

两者文本对齐的参数不一样,导致空隙不一样,见下图PE文件的两种状态

三.DOS头属性说明

1.DOS MZ文件头(结构体 64字节)
第一个成员(2个字节) MZ
最后一个成员(4个字节):指定PE头的位置
2.DOS块:由连接器填写,可以填写任何东西

四.标准PE头的属性说明

1.PE标识(4个字节)
2.标准PE头(20字节)(结构体)
标准PE头
最后两个字节表示文件属性,拆成二进制的,查下表
文件属性_PE

五.扩展PE头的属性说明

扩展PE头(结构体)
扩展PE上
扩展PE下
文件特性,拆成二进制,查下表
文件特性_PE

六.PE节表

结构体数组,每个结构40字节
每个结构体_节表节的属性,拆成二进制
节的属性,拆成二进制

七.RVA与FOA的转换

这里的转换是为了当你得到内存地址时,如何改变文件的地址,进而去改变那个变量的值
相对虚拟地址RVA(内存)
文件偏移地址FOA(文件)

<1>得到RVA的值:内存地址-ImageBase
<2>判断RVA是否位于PE头中,如果是FOA=RVA
<3>判断RVA位于那个节
RVA>=节.VirtualAddress
RVA>=节.VirtualAddress+当前节内存对齐后的大小
差值=RVA-节.VirtualAddress
<4>FOA=节.PointerToRawData+ 差值

核心思想:找到离非空隙区域最近的差值
若对齐方式一样RVA=FOA(新的编译器文件和内存对齐方式一样)


空白区添加代码(简单的一个例子)

<0>构造要写入的代码
<1>在PE的空白区构造一段代码
<2>修改入口地址为 新增代码
<3>新增代码执行后,跳回入口地址

以弹窗指令为例

6A 00 6A 00 6A 00 6A 00 E8 00 00 00 00 E9 00 00 00 00
黄色部分为相对地址算法:
要跳转地址-E8/E9指令当前的地址-5

八.节
一.扩大节

1.为什么要扩大节:插入更多的代码
2.扩大那个节:最后一个节(这样动代码最少)
3.方法:
1.分配一块新的空间,大小为S
2.将最后一个节的SizeOfRawData和Virtualsize改成N
N=(SizeOfRawData或者VirtualSize内存对齐后的值)+S
这两个谁大选哪个
3.修改SizeOfImage大小

二.新增节

1.为什么要新增节:写入更多的代码
2.方法:
<1>判断是否有足够的空间,可以添加一个节表
<2>在节表中新增一个成员
<3>修改PE头中节的数量
<4>修改sizeOfImage的大小
<5>在原有的数据的最后,新增一个节的数据(内存对齐的整数倍)
<6>修正新增节表的属性

三.合并节

1.为什么要合并节:新增节没有地方,DOS块也已经被占用,想要插入代码没有地方,想到合并节来节省空间(这里的合并节对节表操作)
2.方法:
1.按照内存对齐展开(文件和内存文本对齐的参数不一样时这样操作)
2.将第一个的内存大小、文件大小改成一样的
下面是公式

MAX=SizeOfRawData>VirtulSize?SizeOfRawData:VirtulSize
(if语句的简写)
SizeOfRawData=VirtulSize=
最后一个字节的VirtulAddress+Max-SizeOfHeaders内存对齐后的大小
(全部的大小减去头的大小得到全部节的大小(也就是我们合并四个节成一个节的大小))

3.将第一个节的属性改成包含所有节的属性
4.修改节的数量为1

九.表

一个程序由一堆PE文件组成

一.导出表
  • 基本思想:PE文件提供那些功能
    扩展PE头最后最后一部分存了16个结构体,每个结构体宽度8个字节,第一个结构体中存了导出表的地址。
  • 导出表的结构:
    导出表_PE
    函数名称表个数与函数序号表个数相同下图为三张表的关系
    函数名称表个数与函数序号表个数相同
一.导入表(结构体 20字节)

结构
导入表结构
(1)基本思想:PE文件需要依赖模块以及依赖这些模块中的那些函数
(2)位置:扩展PE头最后最后一部分存了16个结构体,每个结构体宽度8个字节,第二个结构体中存了导入表的地址。
(3)
1.依赖几个模块。就有几个导入表
2.但当我们调用其他模块的函数时,都是通过间接CALL来调用
(4)导入表结构体第一个和最后一个都可以找到倒入模块所导入的函数
在这里插入图片描述
(5) PE文件加载前后
加载前
加载前
加载后
加载后

一.重定位表

PE文件如何加载到内存中
(1)功能:
1.排序: 一个EXE加载多个dll时,有可能有些dll的内存起始地址是一样的,这样就需要重定位表安排那个dll占那一块
2.修正:加载的某些dll其中的变量是按照原来内存起始位置存储的,如果调整内存起始地址,变量的位置也要相应修正
(2)位置:扩展PE头最后最后一部分存了16个结构体,每个结构体宽度8个字节,第六个结构体中存了导入表的地址。
(3)结构:重定位表的结构
(4)细节理解细节理解_重定位表

为心中的美好而战 : p

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值