标签:ade virtual mod 开始 header http 数组元素 最大 util
有一些变量是直接赋值一个地址,这个地址如果直接拿来给内存就不对了,因为加载到内存后的地址是随机的。
所以,PE文件创建了多张表,用来存放写死了数据的地址。
重定义表位于可选PE头的数据目录表的第六个元素,也就是索引值为5的结构体
和导出表导入表相同,得到PE头的数据目录表后访问具体的某个数组元素后,进入IMAGE_DATA_DIRECTORY结构体,然后访问VirtualAddress字段来获取地址,然后强转使用。
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
?
sizeofBlock存的同一颜色的块的大小,VitualAddress存放地址RVA
先将数据地址的第一个拿来用,比如说第一个数据地址是0x40001,那么第一个表的VirtualAddress 就是0x40000,然后第一个块下面存放0x1,最大的块的内存为0x1000,超过了就要换下一个块了
VirtualAddress + 存放的偏移地址 = 需要修复的地址RVA
在重定义表结构体下面,都是WORD类型的数据,两个字节两个字节的16位存储,取16位的前四位,如果等于3表示该地址需要修复。
也就是说存放的地址一共16位,前四位是拿来判断该地址是否可以修复,后12位才是来存放地址,真正的地址RVA = 后12位+VirtualAddress
1 拿到可选PE头的对应的数据目录表的第六个重定义表的指向结构体
2 拿到指向结构体对应地址的第一个重定义表的第一个区块
3 利用区块自增来访问每一个区块
4
void CPeUtil::test()
{
//拿到数据目录表
IMAGE_DATA_DIRECTORY directory = pOptionalHeader->DataDirectory[5];
//拿到第一个重定位表
PIMAGE_BASE_RELOCATION RelocationTable = PIMAGE_BASE_RELOCATION(RvaToFoa(directory.VirtualAddress) + FileBuff);
?
//开始遍历重定位表
while (1)
{
if (RelocationTable->VirtualAddress == 0)
{
break;
}
//拿到重定义表的数据的大小
DWORD SizeNumber = (RelocationTable->SizeOfBlock - 8) / 2;
//开始遍历重定义表块的内容
//先拿到第一个数据的地址
WORD* Offset = (WORD*)RelocationTable + 4;
for (int i = 0; i < SizeNumber; i++)
{
if (*Offset & 0x3000 == 0x3000)
{
DWORD Rva = RelocationTable->VirtualAddress + *Offset&0x0FFF;
printf("Rva = %x\n",Rva);
}
Offset++;
}
RelocationTable = RelocationTable + RelocationTable->SizeOfBlock;
}
}
标签:ade virtual mod 开始 header http 数组元素 最大 util
原文地址:https://www.cnblogs.com/Sna1lGo/p/14466837.html