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的转换的更多相关文章

  1. PE知识复习之PE的绑定导入表

    PE知识复习之PE的绑定导入表 一丶简介 根据前几讲,我们已经熟悉了导入表结构.但是如果大家尝试过打印导入表的结构. INT IAT的时候. 会出现问题. PE在加载前 INT IAT表都指向一个名称 ...

  2. PE知识复习之PE的重定位表

    PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思.  如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234.  如果Im ...

  3. PE知识复习之PE的导入表

    PE知识复习之PE的导入表 一丶简介 上一讲讲解了导出表. 也就是一个PE文件给别人使用的时候.导出的函数  函数的地址 函数名称 序号 等等. 一个进程是一组PE文件构成的.  PE文件需要依赖那些 ...

  4. PE知识复习之PE的导出表

    PE知识复习之PE的导出表 一丶简介 在说明PE导出表之前.我们要理解.一个PE可执行程序.是由一个文件组成的吗. 答案: 不是.是由很多PE文件组成.DLL也是PE文件.如果我们PE文件运行.那么就 ...

  5. PE知识复习之PE文件空白区添加代码

    PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...

  6. PE知识复习之PE合并节

    PE知识复习之PE合并节 一丶简介 根据上一讲.我们为PE新增了一个节. 并且属性了各个成员中的相互配合. 例如文件头记录节个数.我们新增节就要修改这个个数. 那么现在我们要合并一个节.以上一讲我们例 ...

  7. PE知识复习之PE新增节

    PE知识复习之PE新增节 一丶为什么新增节.以及新增节的步骤 例如前几讲.我们的PE文件在空白区可以添加代码.但是这样是由一个弊端的.因为你的空白区节属性可能是只读的不能执行.如果你修改了属性.那么程 ...

  8. PE知识复习之PE扩大节

    PE知识复习之PE扩大节 一丶为什么扩大节 上面我们讲了,空白区添加我们的代码.但是有的时候.我们的空白区不够了怎么办.所以需要进行扩大节. 扩大节其实很简单.修改节数据对齐后的大小即可. 并且在PE ...

  9. PE知识复习之PE的节表

    PE知识复习之PE的节表 一丶节表信息,PE两种状态.以及重要两个成员解析. 确定节表位置: DOS + NT头下面就是节表. 确定节表数量: 节表数量在文件头中存放着.可以准确知道节表有多少个. 节 ...

随机推荐

  1. FTP连接虚拟主机响应220 Welcome to www.net.cn FTP service. (解决的一个问题)

    问题场景: 使用FTP客户端连接虚拟主机时,同样的账号密码在有的网络下可以连接成功,有的网络下却一直连接不上:ftp响应“220 Welcome to www.net.cn FTP service.” ...

  2. 关于Python2 与 Python3 的区别

    Python是一门动态解释性的强类型定义语言. 1.Python2 : ①.臃肿,源代码的重复量很多.   ②.语法不清晰,掺杂着C,php,Java的一些陋习. Python3 : 几乎是重构后的源 ...

  3. 【腾讯海纳】系统未发布时如何获取获取property_id在本地进行测试?

    有现成https协议域名使用者,可忽略此文. 直接先上图,明白的人看一眼图片就知道怎么拿了,如下所示: 解释说明: 在完成添加套件,以及测试应用的前提下,按如下操作流程: 1.访问路径:登录“海纳开发 ...

  4. COOKIE和Session的原理及异同

    COOKIE和Session的原理及异同 1. cookie的创建和读取 cookie是客户端技术,服务器把每个用户的数据以cookie的形式写给用户各自的浏览器.当用户使用浏览器再去访问服务器中的w ...

  5. js中的单例模式

    1.场景:当我们需要多人合作完成一个项目,但是有一些操作是同样的操作时(例如:点击按钮显示加载的遮罩层:例如:提交表单时的验证都是一样的),这个时候我们就需要单例模式: 2.什么是单例模式:是一种常见 ...

  6. 2018 大湾区(深圳) .NET技术分享交流会 第一期

    .NET Core 2.1 已于2018年5月30日正式发布,邀请粤港澳大湾区.NET技术专家和从业人员,一起分享与交流.NET技术的发展方向,提高粤港澳大湾区.NET技术交流氛围,挖掘.NET高级人 ...

  7. 【安富莱二代示波器教程】第18章 附件C---波形拟合

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=45785 第18章      附件C---波形拟合 emWin5. ...

  8. JVM,Tomcat与OSGi类加载机制比较

    首先一个思维导图来看下Tomcat的类加载机制和JVM类加载机制的过程 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加载. 比如JVM启动时,会通过不同的类加载器加载 ...

  9. [Swift]LeetCode54. 螺旋矩阵 | Spiral Matrix

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  10. [Swift]LeetCode268. 缺失数字 | Missing Number

    Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...