在前面几节中经常提到相对虚拟地址RVA,在这篇博客中主要说明这个概念。本来是想接着转载小甲鱼的,但是我自己根据这篇文章和他的视频来学习的时候,发现在RVA与文件的相对偏移地址进行转化的时候,那块我看不懂,不知道为什么要这样转化,而且前面很多东西都反复讲了好多遍,比如对齐的问题,所以,这篇我就自己根据自己掌握的情况来写,还是在此处放上原文的连接:

原文(上)传送门

原文(下)传送门

什么是RVA

某个位置的RVA是该位置在内存中的地址相对于整个文件在内存中首地址的偏移值,举个例子,当PE文件中某个全局区中的一个数值所在内存的地址为0x0040871234,而PE文件被系统加载到内存时,它的的首地址为0x00400000,那么这个数值的RVA就是0x0040871234 - 0x00400000 = 0x871234

RVA到文件偏移的转化

有了RVA之后,发现所有数据在内存中进行索引都十分的方便,只要有了基地址和RVA后,通过基地址 + RVA就可以找到对应的数据,但是在PE中并没有类似值来记录某个数据到文件头的偏移,而且由于PE文件在内存中和在磁盘中的对齐值不同,造成某个数据在内存中的偏移和在磁盘中的偏移也不同,这样在磁盘中找到某些值就比较困难

虽然PE文件在内存中的对齐值与在磁盘中的不同,各个区块在内存中的地址与在文件中的不同,但是各个区块里面数据的摆放基本是一样的,也就是在区块中,某个值相对于区块首地址的偏移是一样的,现在定义这样几个变量:

Rva:某个数值在内存中的偏移

Voffset:节点首地址在内存中相当于基地址的偏移

Roffset:节点首地址在磁盘中相当于文件头的偏移

fRva:某个数值在磁盘中相对于文件头的偏移

根据上面的等量关系,可以得到这样的方程:

fRva - Roffset = Rva - Voffset

==>fRva = Rva- Voffset + Roffset

根据这个公式来计算时需要进行如下的步骤:

1. 根据某个Rva落在哪个区块中:取每个节区在内存中的首地址(IMAGE_SECTION_HEADER中的VirtualAddress值) + 区块真实大小(IMAGE_SECTION_HEADER中的VirtualSize),如果Rva小于这个值得话,说明是落在这个节中

2. 通过第一步,我们可以知道Rva处于哪个区块,这样就可以得到区块的首地址在磁盘中相对于文件头的偏移就也就是Voffset的值。

3. 在文件中根据IMAGE_SECTION_HEADER中的PointerToRawData值可以得到这个区块在磁盘中相当于文件头的首地址,这样通过上述公式可以计算出Rva在文件中的偏移

最终得到的公式如下:

fRva = Rva - VirtualAddress + PointerToRawData

举个例子,用lordPE这个工具打开一个.exe文件:



我们来在磁盘中找到ImportTable在磁盘中的入口位置,即0x0001B1C4这个RVA对应在磁盘中的位置

一个个对比发现

.textbss:



这个区块的RVA从0x00001000~0x00011000,这个值不在这个区块内

.text:



这个区块的RVA从0x00011000~0x00016060,这个值不在这个区块内

.rdata



这个区块的RVA从0x00017000~0x0001903d,这个值不在这个区块内

.data



这个区块的RVA从0x0001A000~0x000A158C,这个值不在这个区块内

.idata



这个区块的RVA从0x0001B000~0x0001BAF2,这个值在这个区块内

根据上面的信息可以得到

fRva = Rva - VirualAddress + PointerToRawData = 0x0001B1C4 - 0x0001B000 + 0x00007A00 = 7BC4

PE文件详解(五)的更多相关文章

  1. PE文件详解(八)

    本文转载自小甲鱼PE文件详解系列教程原文传送门 当应用程序需要调用DLL中的函数时,会由系统将DLL中的函数映射到程序的虚拟内存中,dll中本身没有自己的栈,它是借用的应用程序的栈,这样当dll中出现 ...

  2. PE文件详解(六)

    这篇文章转载自小甲鱼的PE文件详解系列原文传送门 之前简单提了一下节表和数据目录表,那么他们有什么区别? 其实这些东西都是人为规定的,一个数据在文件中或者在内存中的位置基本是固定的,通过数据目录表进行 ...

  3. PE文件详解(四)

    本文转自小甲鱼的PE文件详解系列原文传送门 到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的知识.接下来就该轮到SectionTable (区块表,也成节表). ...

  4. PE文件详解(三)

    本文转自小甲鱼的PE文件详解系列传送门 PE文件到内存的映射 在执行一个PE文件的时候,windows 并不在一开始就将整个文件读入内存的,二十采用与内存映射文件类似的机制. 也就是说,windows ...

  5. PE文件详解(九)

    本篇文章转载自小甲鱼的一篇日志,原文地址 我们知道,Windows 将程序的各种界面定义为资源,包括加速键(Accelerator).位图(Bitmap).光标(Cursor).对话框(Dialog ...

  6. PE文件详解(七)

    本文转载自小甲鱼PE文件讲解系列原文传送门 这次主要说明导出表,导出表一般记录着文件中函数的地址等相关信息,供其他程序调用,常见的.exe文件中一般不存在导出表,导出表更多的是存在于dll文件中.一般 ...

  7. PE文件详解二

    本文转自小甲鱼的PE文件相关教程,原文传送门 咱接着往下讲解IMAGE_OPTIONAL_HEADER32 结构定义即各个属性的作用! 接着我们来谈谈 IMAGE_OPTIONAL_HEADER 结构 ...

  8. PE文件结构详解(五)延迟导入表

    PE文件结构详解(四)PE导入表讲 了一般的PE导入表,这次我们来看一下另外一种导入表:延迟导入(Delay Import).看名字就知道,这种导入机制导入其他DLL的时机比较“迟”,为什么要迟呢?因 ...

  9. PE文件结构详解(六)重定位

    前面两篇 PE文件结构详解(四)PE导入表 和 PE文件结构详解(五)延迟导入表 介绍了PE文件中比较常用的两种导入方式,不知道大家有没有注意到,在调用导入函数时系统生成的代码是像下面这样的: 在这里 ...

随机推荐

  1. 【leetcode】123. Best Time to Buy and Sell Stock III

    @requires_authorization @author johnsondu @create_time 2015.7.22 19:04 @url [Best Time to Buy and Se ...

  2. Android的init过程:init.rc解析流程

    这几天打算看下安卓的代码,看优秀的源代码也是一种学习过程,看源代码的过程就感觉到,安卓确实是深受linux内核的影响,不少数据结构的使用方法全然一致.花了一中午时间,研究了下init.rc解析过程,做 ...

  3. Bootstrap的js插件之按钮(button)

    1)属性: data-loading-text="载入中..."--使button呈现载入状态: data-toggle="button"--使按钮可以切换状态 ...

  4. java萌新尝试搭建WordPress记录

    问题1:安装好PHP环境没找好mysql路径,导致不能调用数据库模块 解决方案:重装一次,参考链接 https://www.cnblogs.com/yangxia-test/p/4174372.htm ...

  5. SQL语句 insert into 语句的写法

    方式1: INSERT INTO t1(field1,field2) VALUE('001','002'); 最好的做法明确插入的每一列,列于查错,而且漏列的几率会降低! 方式2: INSERT IN ...

  6. 转:java泛型

    1.为什么需要泛型 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52230032 泛型在Java中有很重要的地位,网上很多文章罗列各 ...

  7. gcc编译相关tips

    http://blog.csdn.net/benpaobagzb/article/details/51364005 静态库链接时搜索路径顺序: ld会去找GCC命令中的参数-L 再找gcc的环境变量L ...

  8. DDOS学习笔记(《破坏之王-DDOS攻击与防范深度剖析》)

           最近花了点时间把<破坏之王-DDOS攻击与防范深度剖析>看了一遍,坦白来说,这本书比较浅显,可以说是入门书,当然对于我这种对DDOS一知半解的人来说,也是一本不错的书,起码我 ...

  9. nginx编译参数的内容

    最近公司安排我安装几台云服务器环境 采用nginx做反向代理: 查了一下官方文档,参数比较多,很多在上线后 可能才知道注意一下的. 编译安装nginx的话 需要安装一些前置组件: 1.gcc环境:用于 ...

  10. Qt---Javascript/Qt交互、脚本化

    Qt提供了对Javascript的良好支持, 如果查阅过文档你就知道Qt有两个不同的Js封装引擎: QScriptEngine QJSEngine QScriptEngine出现的比较早(自Qt4.3 ...