PE知识复习之PE的RVA与FOA的转换

时间:2023-02-09 07:39:52

            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知识复习之PE的RVA与FOA的转换

三丶转换方法

既然上方了解了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

程序截图:

  PE知识复习之PE的RVA与FOA的转换

此时我们已经知道了全局变量地址.那么我们要转换到文件中.将这个全局变量地址进行修改.也就是说.我们通过修改文件.达到修改我们的全局变量值的一种手段.

思路:

  1.计算出RVA.  RVA怎么计算我们也知道了.我们需要查看PE中扩展头的ImageBase成员的值. 这里我已经查看好了.值为0x400000. 那么我们的RVA = 19000

  2.判断属于哪个节,计算出差值偏移

PE知识复习之PE的RVA与FOA的转换 在我们的.data节中.差值偏移计算出结果为0.

  3.计算FOA位置.

  因为现在编译器的文件对齐以及内存对齐都是一样了.所以我们不许要进行计算了. 直接就是文件偏移就是FOA位置.

否则我们差值偏移加文件偏移 = = FOA.  现在我们的差值偏移是 0 0 + 节偏移 就是全局变量在文件中的位置.

PE知识复习之PE的RVA与FOA的转换

7400 就是我们的FOA

  4.跳转到FOA修改全局变量的值

PE知识复习之PE的RVA与FOA的转换

跳转到我们的FOA位置,可以看到我们全局变量的初始值为小端模式的 0x12345678,那么我们进行修改.进行文件保存即可.

 5.修改文件重新打开程序

PE知识复习之PE的RVA与FOA的转换

  修改为0x55555555了,重新打开程序观看结果.

PE知识复习之PE的RVA与FOA的转换

这就是内存转文件偏移的实战. 如果学过逆向的人应该接触过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. PhpStorm 2016&period;3 For Mac 重大里程碑更新 -- 终于解决了不能输入中文标点符号的重大bug

    PhpStorm 2016.3 For Mac 重大里程碑更新 1.[终于解决了]不能输入中文标点符号的重大bug,如 逗号“,”.“.”: 2.可以在一个窗体中,同时打开多个项目: 3.其他... ...

  2. Qt Creator pro 文件 导入vs2013碰到的问题

    显示error LNK1117:sytax error in option... 解决办法 从Properties --> Linker --> Command Line 中删掉Addit ...

  3. Codeforces Round &num;363 Fix a Tree&lpar;树 拓扑排序&rpar;

    先做拓扑排序,再bfs处理 #include<cstdio> #include<iostream> #include<cstdlib> #include<cs ...

  4. AC自动机最好讲解

    http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf

  5. Ubuntu下用命令行快速打开各类型文件

    在Ubuntu下,通常用命令行打开文本文件,比如用命令gedit.more.cat.vim.less.但当需要打开其他格式文件时,比如pdf. jpg.mp3格式文件,咱们通常做法是进入到文件所在的目 ...

  6. easyui控件的加载顺序

    使用easyui做布局时,会模仿窗口程序界面,做出一些较复杂的布局.按由外层到内层的顺序: (最外层)panel->tabs->tabs1 ->tabs2->layout-&g ...

  7. perl 解json数组

    <pre name="code" class="cpp">http://11.36.10.82:4000/api/bus?bus=307&f ...

  8. MQTT&comma; XMPP&comma; WebSockets还是AMQP?泛谈实时通信协议选型 good

    Wolfram Hempel 是 deepstreamIO 的联合创始人.deepstreamIO 是一家位于德国的技术创业公司,为移动客户端.及物联网设备提供高性能.安全和可扩展的实时通信服务.文本 ...

  9. perceptual loss

    https://arxiv.org/abs/1603.08155 两个网络:image transfer网络和loss网络 image transfer网络: 将输入图片y通过映射f W (x)得到输 ...

  10. qtp 自动化测试--点滴 自定义显示工具菜单 trzedit

    tools-customize-toolbars-勾选后关闭 2 trzedit 使用winobject 方法取值 Window("驷惠WIN系列[汽车4S连锁管理软件] 6.") ...