PE知识复习之PE的重定位表
PE知识复习之PE的重定位表
一丶何为重定位
重定位的意思就是修正偏移的意思. 如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234. 如果Imagebase 变了成了0x300000, 那么修正之后就是 ImageBase + RVA = 0X300000+1234 = 0x301234.
首先我们知道.一个EXE文件.会调用很多DLL(PE) 有多个PE文件组成.
exe文件启动的基址 (ImageBase) 是0x40000. 假设我们调用三个DLL A B C.
A DLL 在EXE展开的基址位置是0x10000000
那么恰巧 B DLL 展开的位置也是 0x1000000 两个DLL位置展开地方是一样的.那么就出现问题了.
如下图:
这时候操作系统就会给我们进行修正. 将B DLL 换个内存位置. 进行展开. 这也是为什么很多游戏外挂.等等.都选择DLL注入. 因为系统帮你重定位了各种信息. 代码写在DLL中即可.
如下图: B DLL 从0x20.... 展开了.规避了使用相同地址
虽然这样解决了入口基址不一样.内存展开不一样. 但是我们知道.PE文件中有很多RVA .RVA 是相对于ImageBase的偏移进行存放的. 如果PE文件中都是 RVA 那就好办了.
但是不一定呀.
如一下代码所示:
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int g_Value;
int main()
{
g_Value = ; }
查看其反汇编
我们发现,在给全局变量赋值的的时候.地址是一个固定的.他不是 RVA
再次运行截图:
我们发现地址变了. 而且硬编码 是一个固定的. 0x012c813c ,他直接编译到二进制文件中了.
他把 ImageBase + RVA的值. 直接编译到二进制当中. 就是说.这个全局变量的地址. 是一个 RVA + IMAGEBASE 的地址. 但是他是直接编译到二进制中的.
问题所在:
假设A编译的全局变量的地址是 RVA + iMAGEbase 假设是 0x1012345,那么A展开的位置是 0x10..... 那么全局变量地址是正确的. 但是如果B编译的时候.地址也是1012345. 但是模块基址加载不一样.那么就会出问题了.如下图:
根据上面我们发现了问题所在.所以现在我们需要一张表.记录那个地方需要进行重定位. 我们把这个地方的值改一下即可.
也就是要记录我们修改需要重定位的位置.以上图的代码进行反汇编查看.
也就是记录需要重定位的地方即可.
重定位表就是记录所有需要修正的地址.只要有了重定位表.我们就不用担心我们的ImageBase 没有占住位置.
非常重要的一张表.
二丶重定位表的定位以及结构
重定位表.的定位在扩展头中的数据目录中. 数据目录的第6项就是重定位表的 RVA偏移.以及重定位表的大小.
定位到重定位表,那么有额外的结构体来描述重定位表.
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock; //存储的值以字节为单位.字节多大.表示了一个重定位快有多大.
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
看着重定位表就两个成员. 其实非常复杂. 我们设 VirtualAddress 为 x 设 SizeofBlock为Y
如下图所示,一个格子为1个字节.
第一行四个字节为x.也就是 Virtualaddress.. y则是第二个成员
SizeOfBlock 成员你的意思. 以字节为单位.代表重定位的快由多大. 我们知道.一个PE文件需要很多地方进行重定位的.比如这个记录的
大小为16. 也就是两个重定位块,那么我们的重定位表的大小就是如下图所示:
下面则是新的重定位表.结构就是重定位表的结构,如果SzieofBlock大小为20个字节.那么重定位表大小就是20个自己.
第三个依次类推,重定位表的结束是不停的往下找,知道最后一个重定位表的结构成员你都为0
这样设计的原因:
算术题解惑.
比如我们有地址 101234 101235 101236 这种修正的地址有10000个.
那么每个地址有4个字节的. 那么 4 * 10000 = 4万个字节. 也就是我们要准备一张4万个字节的表来保存重定位的.
但是我们发现一个规律.我们要修正的表的偏移都很近, 1234 1235 ....
那么我们可不可以这样那. 我们把 100000取出来. 两个字节存储1234 另外两个地址存储1235,不用准备四个字节了.小的偏移我们两个字节存储.这样的话我们的表的字节就会缩小一半.
VirtuallAddress 就是存储了 100000这个值,也就是需要 ""基址"" 公用的地址.
SizeofBlock 就是下面的偏移由多大, 我们要修正的偏移是 VirtualAddress + sizeofBlock下面的值.
如下图:
我们的重定位表,需要修正的基址是 0x11000,大小是54. 那么需要修正的偏移是 "36b0" "36bc" "36e0"....
我们基址 + 偏移就是要修正的位置.
偏移的概念:
重定位表,是按照一个物理页(4kb)进行存储的. 也就是一个4kb内存,有一个重定位块, 一个重定位表只管自己当前的物理页的重定位.
一个重定位表的记录偏移的大小是2个字节,也就是16位. 而记录偏移的大小. 是由 SizeofBlock决定的.
但是我们记录偏移的位置,12位就够了. 高4位.挪作他用. 并不是记录的才会修正偏移.只有高4位为3的时候.才会进行重定位(基址 + 偏移)
真正修复的位置 virtualaddress + (高四位为3 ? 低12位偏移 : 无所谓的值.)
也就是高四位为3 Vir + 低12位偏移就等于真正要修复的RVA 例如 36b0 高位为3 低12位就是6b0 要修复的RVA = vir + 6b0 ,如果加上当前DLL的ImagebASE 才是真正要修复的虚拟地址 (VA) 我们计算出的是RVA
如果高位不为3,那么这个值是无所谓了.因为内存对齐的原因.
例如上图重定位表. 0x11000代表了当前要进行修复的块位置. 要修复偏移的地址第一个是36b0 . 高位为3是要进行修复.
所以低位为6B0. 所以修复的位置是 0x116b0的位置. 0x116b0 + 当前PE文件的ImageBase就是要进行重定位的位置
当前PE的Imagebase为0x400000 重定位地方为 0x4116b0位置.
我们第一个修正的位置是4116b0位置,从内存中.反汇编查看. 4116b0的位置的值是0x0041813c. 也就是说.这个位置的值.是我们需要重定位的. 也就是我们上面写的程序.为全局变量赋值的时候.全局变量的地址.需要进行更改.
而需要重定位的值. 则是 全局变量的RVA值 + Imagebase 填写到这里面了. 全局变量是在内存中的data节存储着.所以观看前几篇博客.能知道如何定位全局变量在文件的位置.
三丶总结重定位
重定位表有两个成员. VirtuallAddress sizeofBlock
1.virtualladdress 记录了当前物理页需要进行重定位的起始地址.
2.sizeofBlock 记录了重定位表多大.去掉8个字节(重定位表大小) 下面都是记录了重定位表需要重定位的偏移.
3.偏移是2个字节存储. 12位存储偏移. 高4位存储是否进行重定位. 高4位为3则需要进行重定位. virtuall + 低12位 就是要修正的 RVA偏移.
PE知识复习之PE的重定位表的更多相关文章
- PE知识复习之PE的绑定导入表
PE知识复习之PE的绑定导入表 一丶简介 根据前几讲,我们已经熟悉了导入表结构.但是如果大家尝试过打印导入表的结构. INT IAT的时候. 会出现问题. PE在加载前 INT IAT表都指向一个名称 ...
- PE知识复习之PE文件空白区添加代码
PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...
- PE知识复习之PE的导入表
PE知识复习之PE的导入表 一丶简介 上一讲讲解了导出表. 也就是一个PE文件给别人使用的时候.导出的函数 函数的地址 函数名称 序号 等等. 一个进程是一组PE文件构成的. PE文件需要依赖那些 ...
- PE知识复习之PE的导出表
PE知识复习之PE的导出表 一丶简介 在说明PE导出表之前.我们要理解.一个PE可执行程序.是由一个文件组成的吗. 答案: 不是.是由很多PE文件组成.DLL也是PE文件.如果我们PE文件运行.那么就 ...
- PE知识复习之PE新增节
PE知识复习之PE新增节 一丶为什么新增节.以及新增节的步骤 例如前几讲.我们的PE文件在空白区可以添加代码.但是这样是由一个弊端的.因为你的空白区节属性可能是只读的不能执行.如果你修改了属性.那么程 ...
- PE知识复习之PE的RVA与FOA的转换
PE知识复习之PE的RVA与FOA的转换 一丶简介PE的两种状态 首先我们知道PE有两种状态.一种是内存展开.一种是在文件中的状态.那么此时我们有一个需求. 我们想改变一个全局变量的初始值.此时应该怎 ...
- PE知识复习之PE合并节
PE知识复习之PE合并节 一丶简介 根据上一讲.我们为PE新增了一个节. 并且属性了各个成员中的相互配合. 例如文件头记录节个数.我们新增节就要修改这个个数. 那么现在我们要合并一个节.以上一讲我们例 ...
- PE知识复习之PE扩大节
PE知识复习之PE扩大节 一丶为什么扩大节 上面我们讲了,空白区添加我们的代码.但是有的时候.我们的空白区不够了怎么办.所以需要进行扩大节. 扩大节其实很简单.修改节数据对齐后的大小即可. 并且在PE ...
- PE知识复习之PE的节表
PE知识复习之PE的节表 一丶节表信息,PE两种状态.以及重要两个成员解析. 确定节表位置: DOS + NT头下面就是节表. 确定节表数量: 节表数量在文件头中存放着.可以准确知道节表有多少个. 节 ...
随机推荐
- [CF1140C]Playlist
Description: 给你n首歌,每首歌有一个长度\(a_i\)和美丽度\(b_i\) 现在可以选出最多k首,动听值为\(\sum a_i*min_{\sum b_i}\) Hint: \(n \ ...
- 安装使用eclipse
安装使用eclipse 目标 java学习需要,老师说要安装eclipse,,其实已经下了IDEA了,不过还是听老师的比较好( 准备 jre 也就是java运行环境,因为之前就下了jdk(里面包含jr ...
- wpa_cli 关联无线网络
fq关联无线网络,不同的无线网络认证方式不同设置: 1)open(开放式认证方式,分为): wpa_cli -iwlan0 set_network 0 ssid '"w ...
- C#找不到ConfigurationManager类
c#添加了Configuration;后,竟然找不到 ConfigurationManager 这个类,后来才发现:虽然引用了using System.Configuration;这个包,但是还是不行 ...
- Angular 2项目的环境配置和项目搭建
AngularJS2 发布于2016年9月份,它是基于ES6来开发的. AngularJS2 是一款开源JavaScript库,由Google维护,用来协助单一页面应用程序运行.AngularJS2 ...
- Java 将容器 Map中的内容保存到数组
import java.util.Map; import java.util.HashMap; import java.util.Map.Entry; public class mapToArr { ...
- zookeeper使用和原理探究
转:http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html zookeeper介绍 zookeeper是一个为分布式应用提供一致 ...
- 纯css修改单选、复选按钮样式
只支持IE9及以上 html <label><input class="radio" type="radio" name="radi ...
- docker 数据卷管理
在生产环境中使用docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这涉及到容器对数据管理的操作 容器对数据的管理主要有两种方式: 数据卷(Data Volumes): 容器内 ...
- 日常问题181101: ueditor文本编辑器
下载地址: https://ueditor.baidu.com/website/download.html#ueditor 把下载好的文件整个复制到根目录(或是,想要存放的目录) 引入css: < ...