问题一:什么是基址重定位?

答:重定位就是你本来这个程序理论上要占据这个地址,但是由于某种原因,这个地址现在不能让你霸占,你必须转移到别的地址,这就需要基址重定位。打个比方:例如你现在计划在某某地方建一栋楼,但是有一天你收到上边的通知,这个地方政府临时要征用建公厕,所以这时候你就没辙,得去别的地方建啦~

问题二:为什么需要基址重定位?

答:其实这个问题看起来跟前边的有点重复不是? 但是有些朋友可能会这么说,老湿你的言论是可以,但是放在程序中,你上节课不是还说每个程序都让Windows 欺骗了吗 —— 每个程序觉得自己都完全占有 4GB的内存空间,何来地址被别的程序占据了呢?! 
首先,能够提出问题的朋友都是值得表扬和鼓励的
但是,上节课我们谈了什么内容呢 ? 谈了导出表,为什么会出现导出表呢 ? 正是因为有DLL 这类破坏别人家庭幸福的“小三”的存在~ 
我们之前谈过,动态链接库它自己是没有占据任何似有空间的,都是寄生在应用程序的私有空间里边。那寄生在别人家里,睡在哪里就肯定不是小三说了算啦,肯定要由主人决定不是? 所以,在小三的眼里,不用说,肯定永远都睡在大房,但客观事实告诉我们,经常只能住卧室~(有点扯远了,其实想说的是,基址重定位就是这么被需求的^_^)

问题三:我们需要对程序中的哪些语句(指令)进行基址重定位呢?

答:请先看下图

这是上节课我们用到的动态链接库 Counter.dll 文件,对其用W32Dasm 进行反汇编的截图。我们分析下,有哪些语句是需要我们来进行基址重定位的呢 ?

答案是——但凡涉及到直接寻址的指令都需要进行重定位处理!注意直接寻址和间接寻址。

那么我们再过头来看下图片,一眼就能扫出以下指令需要对其进行重定位:
:10001026 FF0500300010            inc dword ptr [10003000]
:1000102C FF3500300010            push dword ptr [10003000]
:1000103D A100300010              mov eax, dword ptr [10003000]
:10001049 FF0D00300010            dec dword ptr [10003000]
:1000104F FF3500300010            push dword ptr [10003000]
:10001060 A100300010              mov eax, dword ptr [10003000]
:1000106A FF2500200010            Jmp dword ptr [10002000]

那有些朋友可能会问了,类似于“:10001038 E8CFFFFFFF        call 1000100C”的指令,为什么后边显示的是call + 地址,而机器码却不包含地址信息呢? CPU神了? 莫非地址信息被加密了? 其实不是的,学过汇编的朋友不知道还记不记得,在讲call 原理的时候用了大部分时间在谈几种跳转,其中经常遇到的就是“地址+偏移”的形式。那这就能有个说得通的解释了:CFFFFFFFh 事实上就是一个偏移地址,记得咱这是little-edition,转换过来就是FFFF FFCFh,也就是等于-31h。那么1000103Dh - 31h == 1000100Ch,Perfect! ^_^

问题四:系统对一条指令进行重定位需要哪些信息?

答:我们还是拿上边那张图片来说事儿,我们说了上边的那些指令需要重定位,现在就假设重定位后的基地址由原来的10000000h 变为 20000000h了,那么类似这样的语句:inc dword ptr [10003000] 应该改成 inc dword ptr [20003000] 。
注意,重定位的算法我们可以总结为:将直接寻址指令中的双字地址加上模块的实际装入地址与模块建议装入地址之差。

从上边的信息中我们看到,需要进行重定位需要三个因素:
1. 需要修正的地址(10003000h)
2. 建议装入的地址(10003000h)
3. 实际装入的地址(20003000h)

问题五:这些信息哪些应该被保存在重定位表中?

聪明的我们可以发现:
1. 建议装入的地址在PE 文件头中已经定义了
2. 实际装入的地址在没有被装载器装入我们根本无从得知,也就是说这事天不知地不知我们不知只有装载器知道……

因此,我们可以得到的结论是:PE 文件的重定位表(Base Relocation Table)中保存的就是文件中所有需要进行重定位修正的代码的地址。

基址重定位结构表

IMAGE_BASE_RELOCATION STRUC

VirtualAddress        DWORD        ?  ; 重定位数据开始的RVA 地址
      SizeOfBlock           DWORD         ?  ; 重定位块得长度
      TypeOffset             WORD           ?  ;  重定项位数组
IMAGE_BASE_RELOCATION  ENDS

VirtualAddress 是 Base Relocation Table 的位置它是一个 RVA 值;
SizeOfBlock 是 Base Relocation Table 的大小;
TypeOffset 是一个数组,数组每项大小为两个字节(16位),它由高 4位和低 12位组成,高 4位代表重定位类型,低 12位是重定位地址,它与 VirtualAddress 相加即是指向PE 映像中需要修改的那个代码的地址。

IMAGE_REL_BASED_ABSOLUTE           (0) 使块按照32位对齐,位置为0。
IMAGE_REL_BASED_HIGH                    (1) 高16位必须应用于偏移量所指高字16位。
IMAGE_REL_BASED_LOW                    (2) 低16位必须应用于偏移量所指低字16位。
IMAGE_REL_BASED_HIGHLOW            (3) 全部32位应用于所有32位。
IMAGE_REL_BASED_HIGHADJ              (4) 需要32位,高16位位于偏移量,低16位位于下一个偏移量数组元素,组合为一个带符号数,加上32位的一个数,然后加上8000然后把高16位保存在偏移量的16位域内。
IMAGE_REL_BASED_MIPS_JMPADDR   (5)  Unknown
IMAGE_REL_BASED_SECTION              (6)  Unknown
IMAGE_REL_BASED_REL32                  (7)  Unknown

实践:

VirtualAddress:1000H

SizeOfBlock:18H   (计算需要多少地址需要重定义:18-8(前面暂用的8个字节),10/2,等于8)

TypeOffset01:3028H,那么重定义地址为1028=1000+28

TypeOffset01:302E

。。。

24. PE结构-PE详解之基址重定位详解相关推荐

  1. PE结构基址重定位表

    PE体系 PE结构&整体叙述 PE结构&导入表 PE结构&导出表 PE结构&基址重定位表 PE结构&绑定导入实现 PE结构&延迟加载导入表 重定位表定位 ...

  2. 21. PE结构-PE各个结构的基本概念

    exe与dll几乎没什么区别,唯一区别就是一个字段标识出这个文件是exe还是dll 32位叫PE32,64位叫PE32+ PE主要定义在winnt.h vc搜索:image format,定义PE结构 ...

  3. Android的ELF文件重定位详解,包括64位

    0x01 引言 ELF文件格式,主要基于两种,一种是基于链接视图,链接视图即是基于节(Section)来进行解析,一种是基于执行视图,执行视图即是基于段(Segment)来进行解析.前一种是用于静态分 ...

  4. 23. PE结构-PE详解之输出表(导出表)

    为每一个程序写一个相同的函数看起来似乎有点浪费空间,因此Windows就整出了动态链接库的概念,将一些常用的函数封装成动态链接库,等到需要的时候通过直接加载动态链接库,将需要的函数整合到自身中,这样就 ...

  5. 22. PE结构-PE详解之输入表(导入表)、屠龙刀W32Dasm(静态)、LordPE(动态)工具入门(查找dll、调用函数)

    我们知道PE 文件中的数据被载入内存后根据不同页面属性被划分成很多区块(节),并有区块表(节表)的数据来描述这些区块.这里我们需要注意的问题是:一个区块中的数据仅仅只是由于属性相同而放在一起,并不一定 ...

  6. 25. PE结构-PE详解之资源

    资源结构 资源是PE 文件中非常重要的部分,几乎所有的PE 文件中都包含着资源,与导入表和导出表相比,资源的组织方式要复杂很多,其实我们只要看下图就知道俺所言不虚. 分3级:1 资源类型 ,2 资源I ...

  7. 【EXE PE】了解pe段--PE结构详解

    来源:看雪论坛http://bbs.pediy.com/showthread.php?t=145912 1 基本概念 下表描述了贯穿于本文中的一些概念: 名称 描述 地址 是"虚拟地址&qu ...

  8. PE结构详解(64位和32位的差别)

    1 基本概念 下表描述了贯穿于本文中的一些概念: 名称 描述 地址 是"虚拟地址"而不是"物理地址".为什么不是"物理地址"呢?因为数据在内 ...

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

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

最新文章

  1. 【OpenCV 4开发详解】图像二值化
  2. python有哪些作用-python能用来做什么?Python都有哪些逆天的功能
  3. linux知识记录20192022
  4. Matlab C++混合编程 在VisualStudio下的编程 使用了Opencv库
  5. Spring思维导图,让Spring不再难懂(ioc篇)
  6. python requests 上传文件_Python requests上传文件实现步骤
  7. linux rsync 目录同步,linux下使用rsync同步目录
  8. 微信小程序登录后跳转tabbar页面
  9. Linux下MinDoc安装使用
  10. 《Python编程:从入门到实践》配套源代码下载
  11. spring cloud 解决问题
  12. android移植(二)-4的尝试移植过程
  13. html知识点总结1
  14. 智能合约vote部署
  15. 直线电机平台在XY轴上的应用!
  16. css表头固定样式的方法
  17. 使用xml模板生成word文档
  18. Libnids--函数调用顺序之nids_init()
  19. 华为OD机试题java-【招聘】
  20. 钢管制造业数字化信息化——基于odoo架构的ERP批次管理模块

热门文章

  1. 基因组中的趣事(一):这个基因编码98种转录本
  2. 文章用图的修改和排版(2)
  3. python安装matlab库_[python][matlab]在python36上安装matlab2015b引擎
  4. Python相关的考试和认证
  5. 项目管理中网络图的看法和相关参数阅读说明
  6. 【PMP学习笔记】:二、项目运行环境
  7. 判断是否是数字类型php_PHP函数补完:判断变量是否为数字is_numeric()
  8. g++ 安装python_卧槽,又一款Python神器
  9. Python笔记-置信区间含义及运算
  10. Arduino笔记-外部中断实验(震动传感器实时亮灯)