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决定了加载后的基 ...
随机推荐
- sql---->sql-summary&mysql-summary
数据库操作: 1.创建数据库,并修改默认字符编码 create database 数据库名 [charset=字符编码]; ee: create database dog charset=utf8; ...
- Django使用admin管理后台管理数据库表
1.在admin.py文件中注册需要创建的表,例: from .models import * # Register your models here. admin.site.register(Use ...
- 20170928xlVBA自定义分类汇总
SubtotalByCQL Range("A1:E100").Value, "Select 1,2,Sum(4),Count(4) GroupBy 1,2", ...
- Python Signal 信号
https://blog.csdn.net/kongxx/article/details/50976802 http://blog.itpub.net/7728585/viewspace-214206 ...
- 【PowerDesigner】【1】简单介绍
正文: 创建表格 File→New Model→(Model types; Physical Data Model; Physical Diagram)Model name:名称:DBMS:数据库类型 ...
- 将一台电脑上的虚拟机上的系统复制到另一台电脑的虚拟机上!!!and想询问大神们问题的解决办法??
虚拟机是Oracle VM VitualBox版本 前段日子oracle老师让课下安装虚拟机+windows8+oracle数据库,但悲伤的我安了七八遍(重装系统+安装数据库+配置数据库)依旧在配置数 ...
- Oracle11g温习-第二十章:数据装载 sql loader
2013年4月27日 星期六 10:53 1. sql loader :将外部数据(比如文本型)数据导入oracle database.(用于数据导入.不同类型数据库数据迁移) 2.sqlloade ...
- MIR7预制发票扣除已经预制的数量(每月多次预制,未即时过账)
业务场景见抬头,有没有标准的解决方案就不说了,也没去考虑... 这个增强还是SAP老表提供的,感谢,省了不少时间. INCLUDE:LMR1MF6S 最后的位置 ENHANCEMENT ZMIR7_0 ...
- Thirft框架介绍
1.前言 Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目.Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和 ...
- vijos 1512 SuperBrother打鼹鼠
背景 SuperBrother在机房里闲着没事干(再对比一下他的NOIP,真是讽刺啊......),于是便无聊地开始玩“打鼹鼠”...... 描述 在这个“打鼹鼠”的游戏中,鼹鼠会不时地从洞中钻出来, ...