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 重定位表的更多相关文章

  1. PE结构之重定位表

    什么是重定位: 重定位就是你本来这个程序理论上要占据这个地址,但是由于某种原因,这个地址现在不能让你占用,你必须转移到别的地址,这就需要基址重定位.你可能会问,不是说过每个进程都有自己独立的虚拟地址空 ...

  2. 逆向-PE重定位表

    重定位表 ​ 当链接器生成一个PE文件时,会假设这个文件在执行时被装载到默认的基地址处(基地址+RVA就是VA).并把code和data的相关地址写入PE文件.如果像EXE一样首先加载就是它image ...

  3. Windows PE第6章 栈与重定位表

    第六章 栈与重定位表 本章主要介绍栈和代码重定位.站和重定位表两者并没有必然的联系,但都和代码有关.栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构. ...

  4. Reverse Core 第二部分 - 16&17章 - 基址重定位表&.reloc节区

    第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x00 前言 这几天忙着挖邮箱漏洞,吃火锅,马上要被关禁闭,看书进度比较 ...

  5. 基址重定位表&.reloc节区

    第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x01 PE重定位 若加载的是DLL.SYS文件,且在ImageBase ...

  6. ELF 动态链接 - so 的 重定位表

    动态链接下,无论时可执行文件还是共享对象,一旦对其他共享对象有依赖,也就是所有导入的符号时,那么代码或数据中就会有对于导入符号的引用.而在编译时期这些导入符号的确切地址时未知的.只有在运行期才能确定真 ...

  7. PE格式第七讲,重定位表

    PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...

  8. PE知识复习之PE的重定位表

    PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思.  如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234.  如果Im ...

  9. WindowsPE权威指南-PE文件头中的重定位表

    PE加载的过程 任何一个EXE程序会被分配4GB的内存空间,用户层处理低2G的内存,驱动处理高2G的内存. 1.双击EXE程序,操作系统开辟一个4GB的空间. 2.从ImageBase决定了加载后的基 ...

随机推荐

  1. 怎样在winform中上传图片

    http://jingyan.baidu.com/article/b7001fe157d6b60e7382dd7f.html 因为WinForm都是运行在本地的,而我们的网站一般都是布署在服务器上,运 ...

  2. hdu-1115 计算几何 求重心 凸多边形 面积

    思想是分割成三角形,然后求三角形的重心.那么多边形重心就是若干个三角形的重心带权求中心,可以用质点质心公式. #include <cstdio> #include <iostream ...

  3. Vue.js总结 [2017.6.5]

    <head> <script src="https://unpkg.com/vue/dist/vue.js"></script> </he ...

  4. CRM系统之stark组件流程分析

    CRM系统主要通过自定义stark组件来实现的(参照admin系统自定义): STARK组件: 1 admin组件 1 如何使用admin 2 admin源码 3 创建自己的admin组件:stark ...

  5. 二十一、MVC的WEB框架(Spring MVC)

    一.基于注解方式配置 1.首先是修改IndexContoller控制器类 1.1.在类前面加上@Controller:表示这个类是一个控制器 1.2.在方法handleRequest前面加上@Requ ...

  6. redis 管道原理

    命令行使用管道(命令以换行符分隔): (printf "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379 redis ...

  7. Cppcheck - A tool for static C/C++ code analysis

    cppcheck是一个个检测源码的工具,对编译工具的一个补充,mark Cppcheck - A tool for static C/C++ code analysis Syntax: cppchec ...

  8. Linux几种服务用处介绍

    rexec--Remote Execute,远程命令执行,允许远程机器在本机上远程执行命令,监听端口512. nfs--Network File System,网络文件系统,用于将本机文件夹共享到别的 ...

  9. 批量生成QRcode

    本想在excel批量生成GUID,并生成二维码. //Excel生成guid,uuid 格式:600d65bc-948a---fd8dfeebb1cd =LOWER(CONCATENATE(DEC2H ...

  10. 禁止网站被别人通过iframe引用

    https://blog.csdn.net/dugujiancheng/article/details/51669164 解决方案一:js方法这种方法不可靠,不推荐使用 <script type ...