PE文件 03 重定位表
0x01 重定位表结构
重定位表是由数据目录表中的第六个成员指出的:
typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
 
程序编译时每个模块有一个优先加载地址ImageBase,这个值是链接器给出的,因此链接器生成的指令中的地址是在假设模块被加载到ImageBase前提之下生成的,那么一旦程序没有将模块加载到ImageBase时,那么程序中的指令地址就需要重新定位,从而需要重定位表的修正。
对于EXE应用程序来说,在自己独立的4G进程空间中,它是肯定加载到ImageBase默认基地址上的。但是动态链接库就不一样了,动态链接库都是映射到别的应用程序的空间中的,所以出现要载入的基地址被应用程序占据了也是很正常的,这时它就必须进行重定位了。
重定位的算法功能可以描述为:将直接寻址指令中的地址加上模块实际装入地址与模块建议(默认)装入地址之差。
参与运算的是这3个数据:需要修正的机器码地址, 模块的实际装入地址,模块的建议(默认)装入地址ImageBase.而模块的建议(默认)装入地址已经ImageBase中定义了,而模块的实际装入地址是Windows加载器确定的, 因此,PE文件的重定位表中唯一保存的就是一组需要修正的代码的地址。
(位置)重定位表一般会被单独存放在一个以“.reloc”命名的节中,但这并不是必然的,因为重定位表放在其他节中也是合法的,但是如果重定位表存在的话,它的地址肯定可以在数据目录中找到。
为了节省空间,重定位表对需要重定位的指令的地址的存放方式做了一些优化。
直观上看,x86下每个32位的指针占用4个字节,如果有n个重定位项,那么重定位表的总大小就是4×n字节大小。
直接寻址指令在程序中还是比较多的,在相临近的各个重定位表项中,32位指针的高位地址总是相同的,如果将这些相近表项的高位地址只用少数几位来统一表示,那么就可以节省一部分的空间。
当按照一个内存页来分割时,在一个页面中寻址需要的指针位数是12位(一页4096字节,2的12次方),将这12位按WORD对齐为16位,再用一个附加的DWORD来表示页的起始指针,另一个DWORD来表示本页中的重定项数,那么占用的总空间就是4+4+2×n字节大小,当某个内存页中的重定位项多于4项的时候,后一种方法的占用空间就会比前面的方法要小。0
PE文件中重定位表的组织方法就是采用类似的按页分割的方法,从PE文件头的数据目录中得到重定位表的地址后,这个地址指向的就是顺序排列在一起的很多重定位块,每一块用来描述一个内存页中的所有重定位项。
重定位表由一个个的重定位块组成,如果重定位表存在的话,必定是至少有一个重定位块。因为每个块只负责定位0x1000大小范围内的数据,因此如果要定位的数据范围比较大的话,就会有多个重定位块存在。
每个块的首部IMAGE_BASE_RELOCATION定义如下:
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;  //重定位内存页的起始RVA,本块中所有重定位项中的12位地址加上这个起始地址后就得到了真正的RVA值
DWORD SizeOfBlock;     //重定位块的大小,从这个字段的值可以算出块中重定位项的数量
} IMAGE_BASE_RELOCATION
由于SizeOfBlock=4+4+2×n,也就是sizeof IMAGE_BASE_RELOCATION+2×n,所以重定位项的数量就等于(SizeOfBlock-sizeof IMAGE_BASE_RELOCATION)÷2。
MAGE_BASE_RELOCATION结构后面跟着的n个WORD就是重定位项,每个重定位项的16位数据位中的低12位就是需要重定位的数据在页面中的地址,剩下的高4位用来描述当前重定位项的种类。
所有的重定位块最终以一个VirtualAddress字段为0的IMAGE_BASE_RELOCATION结构作为结束,因此可执行文件的代码总是从装入地址的1000h处开始定义的了(比如装入00400000h处的.exe文件的代码总是从00401000h开始,而装入10000000h处的.dll文件的代码总是从10001000h处开始),要是代码从装入地址处开始定义,那么第一页代码的重定位块的VirtualAddress字段就会是0,这就和重定位块的结束方式冲突了。
  
PE文件 03 重定位表的更多相关文章
- PE结构之重定位表
		
什么是重定位: 重定位就是你本来这个程序理论上要占据这个地址,但是由于某种原因,这个地址现在不能让你占用,你必须转移到别的地址,这就需要基址重定位.你可能会问,不是说过每个进程都有自己独立的虚拟地址空 ...
 - 逆向-PE重定位表
		
重定位表  当链接器生成一个PE文件时,会假设这个文件在执行时被装载到默认的基地址处(基地址+RVA就是VA).并把code和data的相关地址写入PE文件.如果像EXE一样首先加载就是它image ...
 - Windows PE第6章 栈与重定位表
		
第六章 栈与重定位表 本章主要介绍栈和代码重定位.站和重定位表两者并没有必然的联系,但都和代码有关.栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构. ...
 - Reverse Core 第二部分 - 16&17章 - 基址重定位表&.reloc节区
		
第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x00 前言 这几天忙着挖邮箱漏洞,吃火锅,马上要被关禁闭,看书进度比较 ...
 - 基址重定位表&.reloc节区
		
第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x01 PE重定位 若加载的是DLL.SYS文件,且在ImageBase ...
 - ELF 动态链接 - so 的 重定位表
		
动态链接下,无论时可执行文件还是共享对象,一旦对其他共享对象有依赖,也就是所有导入的符号时,那么代码或数据中就会有对于导入符号的引用.而在编译时期这些导入符号的确切地址时未知的.只有在运行期才能确定真 ...
 - PE格式第七讲,重定位表
		
PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...
 - PE知识复习之PE的重定位表
		
PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思. 如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234. 如果Im ...
 - WindowsPE权威指南-PE文件头中的重定位表
		
PE加载的过程 任何一个EXE程序会被分配4GB的内存空间,用户层处理低2G的内存,驱动处理高2G的内存. 1.双击EXE程序,操作系统开辟一个4GB的空间. 2.从ImageBase决定了加载后的基 ...
 
随机推荐
- Solaris 10 disable ipv6
			
亲测有效:) http://thegeekdiary.com/how-to-remove-ipv6-in-solaris-11/
 - 在Spring Boot中使用 @ConfigurationProperties 注解, @EnableConfigurationProperties
			
但 Spring Boot 提供了另一种方式 ,能够根据类型校验和管理application中的bean. 这里会介绍如何使用@ConfigurationProperties.继续使用mail做例子. ...
 - 雷林鹏分享:jQuery EasyUI 树形菜单 - 创建异步树形菜单
			
jQuery EasyUI 树形菜单 - 创建异步树形菜单 为了创建异步的树形菜单(Tree),每一个树节点必须要有一个 'id' 属性,这个将提交回服务器去检索子节点数据. 创建树形菜单(Tree) ...
 - 20170824xlVBA出车对账单
			
Private Sub GetClientAccountList() Dim EndRow As Long Dim i As Long, j As Long Dim m As Long, n As L ...
 - 关于如何获取Google 官方 NavgationView中的控件的方法
			
最近在想要寻找一个好集成的SlidingMenu,看上了官方的DrawLayout,简单易集成 然后如果想动态改变DrawLayout头部的HeaderVIew的资源的话需要先获取到控件 方法如下 n ...
 - 微信小程序地图demo完整
			
<block wx:for="{{data_2}}" wx:key='index' wx:if="{{data_2.length}}"> <v ...
 - 2.5 UML顺序图
			
相关概念 交互 对象之间为实现某一功能而必须实施的协作过程.动态行为,称为交互 消息 对象间的协作与交流表现为一个对象以某种方式启动另一个对象的活动,这种交流在 UML里被定义为消息 顺序图的建模元素 ...
 - Kindergarten CodeForces - 484D (贪心,好题)
			
大意: 给定序列, 求划分为若干段, 使得总贡献最大, 每段的贡献为max-min 可以发现最优解一定是连续一段递增或递减, 然后dp即可. #include <iostream> #in ...
 - Mysql优化系列--Innodb引擎下mysql自身配置优化-转
			
原文链接:http://www.cnblogs.com/kevingrace/p/6133818.html 谢谢楼主 1.简单介绍 InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全 ...
 - 美团点评MySQL数据库高可用架构从MMM到MHA+Zebra以及MHA+Proxy的演进
			
本文介绍最近几年美团点评MySQL数据库高可用架构的演进过程,以及我们在开源技术基础上做的一些创新.同时,也和业界其它方案进行综合对比,了解业界在高可用方面的进展,和未来我们的一些规划和展望. MMM ...