重定位表详解

重定位表对于EXE文件是没有必要的,因为EXE程序是第一个被载入内存的模块。而DLL却是必须需要重定位信息的,因为DLL不一定加载到它默认的ImageBase上。重定位表作为一个单独的区块放到区块表中,其名字一般为.reloc。

PE文件通过将所有可能的修改的数值存放到一个数组里,以一种统一的方式进行修正。
每个重定位信息以一个IMAGE_BASE_RELOCATION开始,采用类似页分割的方式,由许多重定位块组成,每个块是4KB的大小。
IMAGE_BASE_RELOCATION结构如下

typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;//RVA
    DWORD   SizeOfBlock;
} IMAGE_BASE_RELOCATION,* PIMAGE_BASE_RELOCATION;
#define IMAGE_SIZEOF_BASE_RELOCATION         8

VirtualAddress是要修正的数据的基地址。
SizeOfBlock是该重定位结构的大小,重定位结构的大小是不定的,在SizeBlock后面紧跟着的就是一个TypeOffset数组,一个大小是2字节,其中高4位代表修正的类型低16位是修正的偏移。它的大小与VirtualAddress相加就是要修正的RVA地址。当出现一个_IMAGE_BASE_RELOCATION结构体的值全为0时,表明重定位表结束
重定位是DATA_DIRECTORY的第6项。

TypeOffset高4位的可能取值:
在这里插入图片描述IMAGE_REL_BASED_DIR64 出现在64位的PE文件中。对于x86而言,所有的基址重定位类型都是IMAGE_REL_BASED_HIGHLOW。并且在一组重定位信息结束的地方会出现IMAGE_REL_BASED_ABSOLUTE用于对齐操作
下面来实战下。
在这里插入图片描述跳到重定位开始处。
在这里插入图片描述
其VirtualAddress是0x1000,重定位结构的大小是0x10,也就是说,后面跟着的TypeOffset数组的个数是(0x10 - 2 * sizeof(DWORD)) / sizeof(TypeOffset),即4个
在这里插入图片描述
重定位数据分别是

  • 30 0f
  • 30 23
  • 00 00
  • 00 00

很明显的看出最后两个是用于对齐而用的,所以真正有用的是前两个TypeOffset,他们的类型是3,说明类型是IMAGE_REL_BASED_HIGHLOW,所以我们知道了要修正的数据位置为0x100f,0x1023,换算成文件偏移也就是0x60f,0x623。

所以执行PE文件前,Loader会遍历重定位表,找到要修正的数据,然后用 (实际映像地址-默认基址)+该重定位数据地址。

猜你喜欢

转载自blog.csdn.net/qq_40890756/article/details/90080880
今日推荐