PE重定位表

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PE重定位表相关的知识,希望对你有一定的参考价值。

前言

首先看一个问题,假设我们的某个EXE/DLL首选加载地址是0x10000,但实际由于随机基质等原因实际加载地址首选地址产生的偏移

我们首先看一个exe的静态反编译结果

我们看到00411E98这个地址的反汇编指令是MOV EAX,[41A014H]

我们再看看动态加载这个EXE后的结果

这个你可以明显看到这个指令变成了eax dword ptr[09FA014h],这个读取地址从41A014H09FA014h变化。这就是因为基地址实际装载有变化因此需要对于实际地址的命令做出改变。

为了解决这类绝对地址随着实际加载地址的改变PE提出了重定位表的概念

重定位表

重定位表数据偏移放在数据目录第六项

Relocation Table官方文档

我们看一个例子

这个例子中第六项显示出导出数据VA为 1F000h大小为888(十进制 十六进制为378)字节。
另外我们注意这个示例中存在一个section 名字是.reloc,VA为 1F000h 大小为600(十六进制,十进制1536),也就是重定位数据会放在这个节中

这个重定位节的数据结构比较麻烦,.reloc存在若干个IMAGE_BASE_RELOCATION+n* TypeOffset组成

typedef struct _IMAGE_BASE_RELOCATION 
    DWORD   VirtualAddress;
    DWORD   SizeOfBlock;
//  WORD    TypeOffset[1];
 IMAGE_BASE_RELOCATION;


我们现在来详细解释下相关具体字段

OffsetSizeFieldDescription
04Page RVA这个地址加上镜像首选基质 最后分别和每个TypeOffset加和得到需要重定位的地址
44Block Size整个IMAGE_BASE_RELOCATION大小包含若干TypeOffset以及Block Size,Page RVA的大小
82TypeOffset低12表示偏移值,高4位表示偏移类型
n2TypeOffset同上

通过上面简述我们可以到一个结论IMAGE_BASE_RELOCATION中存在TypeOffset的数量是:
n= ([Block Size] - sizeof(Block Size)+sizeof (Page RVA))/sizeof (TypeOffset)
我们进行常量替换得到
n =([Block Size] -8)/2

TypeOffset高4位类别如下所示:

我们本例中重定位范围为:
[1F000h-1F378h]对应文件地址[9000h-9378h]


我们举例分析其中的第一个
00 10 01 00 4C 00 00 00

OffsetSizeFieldValue
04Page RVA00011000
44Block Size0000004C

我们带入公式
n =(4c -8)/2= 22
可见第一个存在22个TypeOffset
因此我们高亮整个数据结构IMAGE_BASE_RELOCATION区域如下图

OffsetSizeFieldValue
04Page RVA00011000
44Block Size0000004C
82TypeOffset高四位:3 低12位:71F
102TypeOffset高四位:3 低12位:73E
2TypeOffset

我们举例其中两个偏移地址的计算:
本例中:
Page RVA =00011000
Base:400000h(这里从本例PE文件给出)

因此第一个重定位的偏移地址为:
00011000+400000+71F=41171F

第二个重定位的偏移地址为:
00011000+400000+73E=41173E

代码实战

我们利用上面所学的知识实现一个功能,手动加载dll并处理重定位,然后调用相关函数。

代码地址

以上是关于PE重定位表的主要内容,如果未能解决你的问题,请参考以下文章

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

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

PE结构-重定位表

《PE总结 》– 重定位表

《PE总结 》– 重定位表

解析PE资源表与重定位表