笔记:PE结构(7)重定位表解析

重定位表 偏移位于 可选头最后一个成员:
0x60_IMAGE_DATA_DIRECTORY DataDirectory[16]; 第6个目录
指向重定位表的偏移 :
IMAGE_DIRECTORY_ENTRY_BASERELOC
struct _IMAGE_DATA_DIRECTORY {
0x00DWORD VirtualAddress;   RVA  模块基址/句柄  + VirtualAddress =重定位表在内存中的位置
0x04 DWORD Size;  没用
};
重定位表块(有很多块这种结构) 每一块的开始部分 是下面这种结构:
srurct_IMAGE_BASE_RELOCATION{
0x00 DWORD VirtualAddress;  RVA
0x04 DWORD SizeofBlock;  块大小
}
结构1 VirtualAddress   4字节  RVA
结构1 SizeofBlock; 4字节 块大小
结构1:数据.(每个数据2字节) 每个高4位值为3的数据都需要修复 (指向的地址)
.....
结构2 VirtualAddress   4字节  RVA
结构2 SizeofBlock; 4字节 块大小
结构2:数据.  (每个数据2字节) 每个高4位值为3的数据都需要修复 (指向的地址)
....
结束标记VirtualAddress值为0
结束标记SizeofBlock; 值为0

重定位表 真正要改的地方是 (VirtualAddress+2字节数据的低12位+模块句柄/模块基址)  指向的地方,而不是表。

结构里的 VirtualAddrsss里面的值,是指这些2字节数据(偏移) 都属于同一个页面( 1页=0x1000)..

举例有两个RVA: 

被拆分的RVA:8551 8132 

VirtualAddrsss7000 

SizeofBlock块大小

那么里面的两个2字节数据  0x1551 0x1132 (忽略了2字节数据的高4位 只是举个例子 实际高4位的值不能加)

那么下一个结构

VirtualAddrsss8000

SizeofBlock 块大小

被拆分的 RVA:9475 9647

那么里面的两个2字节数据  0x1495 0x1647 (忽略了2字节数据的高4位 只是举个例子 实际高4位的值不能加)

....

注意:2个字节的数据 低12位已经足够表示一页(十进制4096)的偏移  高4位挪作它用了 

          如果高4位是3,代表该位置需要修改,不是3,则不用管它。因为这个数据块内存

            对齐(方便找下个块)会补充一些垃圾数据

结构2的地址:是模块基址/句柄  +VirtualAddress重定位表的偏移(目录6))+结构1的SizeofBlock

一个节区可能会有多个需要重定位的块(如果节区大于0x1000的话).

每个块 2字节数据个数=(块大小-8)除以2

最后是:如何修改重定位表中地址所指向的值,用地址指向的值 - 当前程序(exe or dll)的IMAGEBASE + 你准备贴程序的内存首地址(地址需要是页对齐的)。 

重定位表修复后 不清楚IMAGEBASE需不需要修改....


版权声明:本文为Q324411601原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。