typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress; // (重要)需要重定位的位置,这是一个RVA
DWORD SizeOfBlock; // (重要)这个结构体的大小(算上TypeOffset)
// WORD TypeOffset[1]; // (重要)存放的是相对于第一个元素描述的位置的偏移
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
1、当重定位发生的时候,只需知道现在PE文件的加载基址,用现在的加载基址减去默认加载基址得到一个数,再用这个数加上需要重定位的数据即可,所以重定位表中保存的只是需要重定位的数据的位置。
2、重定位表也是一个结构体数组,以全零元素结尾,每一个数组元素描述了4KB大小的区域的重定位信息。
3、结构体第三个成员并不是真正的结构体成员,它紧随在结构体之后,是一个不定多长的数组,第一个成员是一个基址,描述的是某个区段中一个区域的开始,如果在这个区域中每有一个存储全局变量地址的地方(代表需要重定位),下面的第三个成员TypeOffset数组中就会有一个元素和这个位置对应。
4、需要重定位的个数 = (SizeOfBlock - 8) / 2;
5、第三个成员的高4位,描述的是一个属性。低12位描述的才是一个偏移。(大部分重定位属性值都是0x3,代表整个位置的四个字节都需要被修改)。
6、当基址重定位发生的时候,用第一个成员,算出虚拟地址(VA),也就是基址,依次加上偏移(第三个成员的后12位),就能得到存储全局变量地址的相对虚拟地址,也就找到了这个地方,再依据第三个成员高四位描述的属性,对其进行重定位。