PE知识复习之PE的RVA与FOA的转换
PE知识复习之PE的RVA与FOA的转换
一丶简介PE的两种状态
首先我们知道PE有两种状态.一种是内存展开.一种是在文件中的状态.那么此时我们有一个需求.
我们想改变一个全局变量的初始值.此时应该怎么做.你知道虚拟地址.或者文件位置了.那么你怎么自己进行转换.
也就是说通过文件中的节数据找到在内存中这块数据的位置.或者反之.
寻找之前我们要先弄前几个概念.
ImageBase: 模块基址.程序一开始的地址.
VA: 全名virtualAddress 虚拟地址. 就是内存中虚拟地址. 例如 0x00401000
RVA: RVA就是相对虚拟偏移. 就是偏移地址. 例如 0x1000. 虚拟地址0x00401000的RVA就是 0x1000. RVA = 虚拟地址-ImageBase
FOA: 文件偏移. 就是文件中所在的地址.
二丶因为PE的两种状态.所以需要转换.
上面简介了一下什么是VA RVA 以及FOA 那么我们为什么要转换.
原因是这样的. 我们程序的数据.在PE文件中的地址假设是0x400, 那么在内存中展开的时候就是0x1000位置处.
那么我们如何通过内存位置.找到文件中这个数据的位置. 或者反之. 如果找到就可以进行修改了.
原因就是PE有两种状态.有内存对齐跟文件对齐. 如果内存对齐跟文件对齐一样.那么不管在内存中还是在文件中.数据的位置都是一样的.
例如文件对齐是0x1000,内存也是一样. 那么文件中0x1000位置存放的值.跟PE在内存中展开的时候存放的值是一样的.所以就不需要转换了.直接在文件中更改或者在内存中更改就行了.
因为对齐值不一样.所以我们才需要进行转换.
例如下图:
文件对齐值是0x200,内存对齐是0x1000
三丶转换方法
既然上方了解了PE的内存状态.以及文件状态形式. 那么转换就很好理解了.
1.内存转文件偏移计算
1.1.计算RVA
这一个讲的就是内存转文件偏移.就是知道一个内存地址.我们要看看在文件中是哪里存储的.
第一步: 我们知道PE在内存中展开.是在ImageBase位置展开的.头跟文件是一样的.只不过节数据展开位置不一样.
所以首先就是 我们的内存地址-Image得出RVA
下方我们的内存地址我就设为x了.
x - ImageBase == RVA 得出了我们的x位置在内存中的相对偏移.相对偏移就是我们计算的这个地址在开始位置的什么地方.
ImageBase是在扩展头中存放的.我们可以查看一下.具体可以看看前几讲.属性解析.
注意都是16进制进行加算的.
根据上方我们得出的RVA.然后我们就在文件中从开头数RVA个字节,去寻找我们的这个数据.这样是不行的.因为文件对齐跟内存对齐是不一样的.所以我们要考虑对齐方式. 如果文件对齐跟内存对齐一样.那么这样就可以去找.
2.寻址FOA
既然找到了RVA了.那么就找一下FOA在哪里.也就是文件偏移在哪里.寻找这个值很简单.需要几个步骤.
2.1.判断RVA属于哪个节/头.
如果RVA属于头(DOS+NT)那么不需要进行计算了.因为头在文件中根内存中都是一样展开的.直接从开始位置寻找到RVA个字节即可.
如果不在头,就要判断在那个节里面. 判断节开始位置.跟结束位置. 我们的RVA在这个值里面.
其中节虚拟地址结束位置 就是用节数据对齐后的大小+虚拟地址大小. 具体可以参考上一讲节表解析.
公式: RVA >= 节.VirtualAddress && RVA <= (节.VirtualAddress + 节.SizeofRawData)
2.2 计算差值偏移. 虚拟地址距离节数据的开始位置的偏移.
然后计算差值偏移:
差值 = RVA - 节.VirtuallAddress
差值偏移:
为什么要计算差值.因为我们计算的差值偏移就是我们的 RVA距离我们节数据开始位置 的偏移是多少. 因为这个位置是不会改变的.
例如: 节数据开始位置是 0x1000 我们的RVA = 0x1024 那么差值是0x24. 如果文件中节数据开始的位置是0x400. 那么我们的差值偏移是不会变的. 那么文件偏移 + 差值偏移. 那么就是在文件中的位置. 例如 0x424
2.3 计算FOA
FOA就很好计算了. 差值偏移已经得出来了. 就知道我们的RVA距离节数据开始位置的偏移. 那么我们加上文件偏移就是FOA
公式: FOA = 差值偏移 + 节.PointToRawData
内存转文件偏移总结:
1.计算RVA 公式: x - ImageBase == RVA
2.计算差值偏移. RVA - 节.VirtualAddress == 差值偏移.
3.计算FOA 差值偏移 + 节.PointerToRawData == FOA
2.文件偏移转内存虚拟地址
上面讲解了我们根据虚拟地址可以定位到在文件中的那个位置.那么反之.我们也可以通过文件位置.定位到虚拟地址.
需要理解的还是差值偏移. 只不过角色互换了. .
设x 为节数据的任意一位置
1.计算差值偏移: x - 节.PointerToRawData(节数据在文件中开始的位置) == 差值偏移.
2.计算RVA 差值偏移 + 节.VirtuallAddress(节数据在内存中展开的位置) == RVA
3.计算虚拟地址: RvA + ImageBase == VA
需要注意的就是我们的 x在哪一个节中. x <= 节.PointerToRawData + 节.SizeofRawData
四丶实战演练
我们写一个程序.其代码如下:
#include <stdio.h>
#include <stdlib.h> int g_TestValue = 0x12345678;
int main(int argc, char *argv[])
{
printf("全局变量地址 = %p \r\n", &g_TestValue);
printf("全局变量值 = %X \r\n", g_TestValue); getchar();
}
PS: 如果是VS系列编译器,请在属性 -> 连接 中去掉随机基址. 不然你需要计算一下.或者自己在PE中将文件头的文件属性更改. 更改为. 0x0103
程序截图:
此时我们已经知道了全局变量地址.那么我们要转换到文件中.将这个全局变量地址进行修改.也就是说.我们通过修改文件.达到修改我们的全局变量值的一种手段.
思路:
1.计算出RVA. RVA怎么计算我们也知道了.我们需要查看PE中扩展头的ImageBase成员的值. 这里我已经查看好了.值为0x400000. 那么我们的RVA = 19000
2.判断属于哪个节,计算出差值偏移
在我们的.data节中.差值偏移计算出结果为0.
3.计算FOA位置.
因为现在编译器的文件对齐以及内存对齐都是一样了.所以我们不许要进行计算了. 直接就是文件偏移就是FOA位置.
否则我们差值偏移加文件偏移 = = FOA. 现在我们的差值偏移是 0 0 + 节偏移 就是全局变量在文件中的位置.
7400 就是我们的FOA
4.跳转到FOA修改全局变量的值
跳转到我们的FOA位置,可以看到我们全局变量的初始值为小端模式的 0x12345678,那么我们进行修改.进行文件保存即可.
5.修改文件重新打开程序
修改为0x55555555了,重新打开程序观看结果.
这就是内存转文件偏移的实战. 如果学过逆向的人应该接触过OD.或者x64DBG. 如果我们在内存中修改后.要保存到文件.那么计算公式就是这个.
PE知识复习之PE的RVA与FOA的转换的更多相关文章
- PE知识复习之PE的绑定导入表
PE知识复习之PE的绑定导入表 一丶简介 根据前几讲,我们已经熟悉了导入表结构.但是如果大家尝试过打印导入表的结构. INT IAT的时候. 会出现问题. PE在加载前 INT IAT表都指向一个名称 ...
- PE知识复习之PE的重定位表
PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思. 如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234. 如果Im ...
- PE知识复习之PE的导入表
PE知识复习之PE的导入表 一丶简介 上一讲讲解了导出表. 也就是一个PE文件给别人使用的时候.导出的函数 函数的地址 函数名称 序号 等等. 一个进程是一组PE文件构成的. PE文件需要依赖那些 ...
- PE知识复习之PE的导出表
PE知识复习之PE的导出表 一丶简介 在说明PE导出表之前.我们要理解.一个PE可执行程序.是由一个文件组成的吗. 答案: 不是.是由很多PE文件组成.DLL也是PE文件.如果我们PE文件运行.那么就 ...
- PE知识复习之PE文件空白区添加代码
PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...
- PE知识复习之PE合并节
PE知识复习之PE合并节 一丶简介 根据上一讲.我们为PE新增了一个节. 并且属性了各个成员中的相互配合. 例如文件头记录节个数.我们新增节就要修改这个个数. 那么现在我们要合并一个节.以上一讲我们例 ...
- PE知识复习之PE新增节
PE知识复习之PE新增节 一丶为什么新增节.以及新增节的步骤 例如前几讲.我们的PE文件在空白区可以添加代码.但是这样是由一个弊端的.因为你的空白区节属性可能是只读的不能执行.如果你修改了属性.那么程 ...
- PE知识复习之PE扩大节
PE知识复习之PE扩大节 一丶为什么扩大节 上面我们讲了,空白区添加我们的代码.但是有的时候.我们的空白区不够了怎么办.所以需要进行扩大节. 扩大节其实很简单.修改节数据对齐后的大小即可. 并且在PE ...
- PE知识复习之PE的节表
PE知识复习之PE的节表 一丶节表信息,PE两种状态.以及重要两个成员解析. 确定节表位置: DOS + NT头下面就是节表. 确定节表数量: 节表数量在文件头中存放着.可以准确知道节表有多少个. 节 ...
随机推荐
- 第k小的元素
利用快排思想,如果标志位大于k,则第k小的数字在左边,否则在右边.(程序是第k大的元素) #include <iostream> #include <vector> using ...
- 实现logstash6.4.3 同步mysql数据到Elasticsearch6.4.3
本文旨在实践把mysql已有的数据同步到elasticsearch中,使用的版本是6.4.3,对于其它6.x版本理应是一样的处理方式. 本文目录: 1.初始化Elasticsearch 6.4.3 1 ...
- MyBatis 缓存机制
Mybatis 有两级缓存: 一级缓存: 也称为本地缓存,SqlSession级别的缓存.一级缓存是一直开启的: 与数据库同一次会话期间查询到的数据会放在本地缓存中,以后如果需要获取相同的数据,直接从 ...
- [bzoj1088]扫雷
额,这种水题我也不说什么了233 Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的扫雷游戏,这个 ...
- 机器学习(六)K-means聚类、密度聚类、层次聚类、谱聚类
本文主要简述聚类算法族.聚类算法与前面文章的算法不同,它们属于非监督学习. 1.K-means聚类 记k个簇中心,为\(\mu_{1}\),\(\mu_{2}\),...,\(\mu_{k}\),每个 ...
- grafana--邮箱告警配置
安装 wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-6.0.2-1.x86_64.rpm yum l ...
- Linux 管理进程
探查进程 参数 描述 -A 显示所有进程 -N 显示与指定参数不符的所有进程 -a 显示除控制进程(session leader1)和无终端进程外的所有进程 -d 显示除控制进程外的所有进程 -e 显 ...
- PyCharm下载及使用
PyCharm教育版是一款能够对你编写Python程序的工作有所帮助的免费编译器. PyCharm-community下载链接:https://pan.baidu.com/s/1Hwd_TOVA3en ...
- C#转发Post请求,包括参数和文件
/// <summary> /// 转发Post请求 /// </summary> /// <param name="curRequest">要 ...
- QEMU KVM Libvirt手册(11): Managing Storage
When managing a VM Guest on the VM Host Server itself, it is possible to access the complete file sy ...