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头下面就是节表. 确定节表数量: 节表数量在文件头中存放着.可以准确知道节表有多少个. 节 ...
随机推荐
-
PhpStorm 2016.3 For Mac 重大里程碑更新 -- 终于解决了不能输入中文标点符号的重大bug
PhpStorm 2016.3 For Mac 重大里程碑更新 1.[终于解决了]不能输入中文标点符号的重大bug,如 逗号“,”.“.”: 2.可以在一个窗体中,同时打开多个项目: 3.其他... ...
-
Qt Creator pro 文件 导入vs2013碰到的问题
显示error LNK1117:sytax error in option... 解决办法 从Properties --> Linker --> Command Line 中删掉Addit ...
-
Codeforces Round #363 Fix a Tree(树 拓扑排序)
先做拓扑排序,再bfs处理 #include<cstdio> #include<iostream> #include<cstdlib> #include<cs ...
-
AC自动机最好讲解
http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
-
Ubuntu下用命令行快速打开各类型文件
在Ubuntu下,通常用命令行打开文本文件,比如用命令gedit.more.cat.vim.less.但当需要打开其他格式文件时,比如pdf. jpg.mp3格式文件,咱们通常做法是进入到文件所在的目 ...
-
easyui控件的加载顺序
使用easyui做布局时,会模仿窗口程序界面,做出一些较复杂的布局.按由外层到内层的顺序: (最外层)panel->tabs->tabs1 ->tabs2->layout-&g ...
-
perl 解json数组
<pre name="code" class="cpp">http://11.36.10.82:4000/api/bus?bus=307&f ...
-
MQTT, XMPP, WebSockets还是AMQP?泛谈实时通信协议选型 good
Wolfram Hempel 是 deepstreamIO 的联合创始人.deepstreamIO 是一家位于德国的技术创业公司,为移动客户端.及物联网设备提供高性能.安全和可扩展的实时通信服务.文本 ...
-
perceptual loss
https://arxiv.org/abs/1603.08155 两个网络:image transfer网络和loss网络 image transfer网络: 将输入图片y通过映射f W (x)得到输 ...
-
qtp 自动化测试--点滴 自定义显示工具菜单 trzedit
tools-customize-toolbars-勾选后关闭 2 trzedit 使用winobject 方法取值 Window("驷惠WIN系列[汽车4S连锁管理软件] 6.") ...