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. 第k小的元素

    利用快排思想,如果标志位大于k,则第k小的数字在左边,否则在右边.(程序是第k大的元素) #include <iostream> #include <vector> using ...

  2. 实现logstash6.4.3 同步mysql数据到Elasticsearch6.4.3

    本文旨在实践把mysql已有的数据同步到elasticsearch中,使用的版本是6.4.3,对于其它6.x版本理应是一样的处理方式. 本文目录: 1.初始化Elasticsearch 6.4.3 1 ...

  3. MyBatis 缓存机制

    Mybatis 有两级缓存: 一级缓存: 也称为本地缓存,SqlSession级别的缓存.一级缓存是一直开启的: 与数据库同一次会话期间查询到的数据会放在本地缓存中,以后如果需要获取相同的数据,直接从 ...

  4. [bzoj1088]扫雷

    额,这种水题我也不说什么了233 Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的扫雷游戏,这个 ...

  5. 机器学习(六)K-means聚类、密度聚类、层次聚类、谱聚类

    本文主要简述聚类算法族.聚类算法与前面文章的算法不同,它们属于非监督学习. 1.K-means聚类 记k个簇中心,为\(\mu_{1}\),\(\mu_{2}\),...,\(\mu_{k}\),每个 ...

  6. grafana--邮箱告警配置

    安装 wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-6.0.2-1.x86_64.rpm yum l ...

  7. Linux 管理进程

    探查进程 参数 描述 -A 显示所有进程 -N 显示与指定参数不符的所有进程 -a 显示除控制进程(session leader1)和无终端进程外的所有进程 -d 显示除控制进程外的所有进程 -e 显 ...

  8. PyCharm下载及使用

    PyCharm教育版是一款能够对你编写Python程序的工作有所帮助的免费编译器. PyCharm-community下载链接:https://pan.baidu.com/s/1Hwd_TOVA3en ...

  9. C#转发Post请求,包括参数和文件

    /// <summary> /// 转发Post请求 /// </summary> /// <param name="curRequest">要 ...

  10. 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 ...