位于数据目录表的第6个结构,可以得到重定位表的位置。
重定位表分为几个block,
block的第一个4字节是块的virtualAddress ,为页的整数倍(1000H, 也就是4KB 可以用12位来存储)
第二个四字节是block的大小。
下一个块的地址=第一个块的地址+块大小 最后一个kuai的前8字节为0结构
块里面的具体项大小时2字节
两个字节的结构里 前4位为3的重定位时需要修改 后12位+块的VirtualAddress里面存放的为真正需要改的地址
改变imagebase 然后用前面得到的值减去以前的imagebase加上改变后的imagebase即可 重定位表修改完成
修改重定位表
`void ModifyImageBaseAndReloc(PVOID pImage,DWORD ImageBase)
{
PVOID pOptionHeader = NULL;
GetPEOptionHeader(pImage, &pOptionHeader);
//得到原来的ImageBase
DWORD OldImageBase = ((PIMAGE_OPTIONAL_HEADER32)pOptionHeader)->ImageBase;
//修改ImageBase
((PIMAGE_OPTIONAL_HEADER32)pOptionHeader)->ImageBase = ImageBase;
//dwRelocTable_FOA为重定位表在文件中的FOA 重定位表开始的地方
DWORD dwRelocTable_FOA = RVA_To_FOA(pImage,
((PIMAGE_OPTIONAL_HEADER32)pOptionHeader)->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
DWORD SizeOfBlock = *((DWORD*)pImage + dwRelocTable_FOA / 4 + 1);
DWORD BlockData_RVA = *((DWORD*)pImage + dwRelocTable_FOA / 4);
while (BlockData_RVA != 0 && SizeOfBlock != 0)
{
DWORD Index = 0;
WORD* BlockData = ((WORD*)pImage + dwRelocTable_FOA / 2 + 4);;
while (Index<(SizeOfBlock-8)/2)
{
//读取两字节内容,修改前4位=3的内容。如果需要修改 后12位置的内容+virtualAddress (这是一个RVA) 转换成FOA 然后
//在文件中读取4字节
//读取的值-OldImageBase+修改后的ImageBase 写入这个地址
if (*BlockData>>12==3)
{
WORD low_BlockData = (*BlockData & 0xfff);
DWORD ModifyAddress_RVA = BlockData_RVA + low_BlockData;
DWORD ModifyAddress_FOA = RVA_To_FOA(pImage,ModifyAddress_RVA);
DWORD *ModifyData = (DWORD*)((char*)pImage + ModifyAddress_FOA);
*ModifyData = *ModifyData +ImageBase-OldImageBase ;
}
BlockData++;
Index++;
}
//下一个块的FOA=上一个块的FOA+大小
dwRelocTable_FOA += SizeOfBlock;
//得到下一个块的RVA
BlockData_RVA = *((DWORD*)pImage + dwRelocTable_FOA / 4);
//得到下一个块的大小
SizeOfBlock = *((DWORD*)pImage + dwRelocTable_FOA / 4+1);
}
ImageBufferToFile(pImage, "c:/ModifyReloc.dll");
移动重定位表
void MoveRelocTable(PVOID pImage, DWORD Section_FOA)
{
DWORD SizeOfBlocks = GetRelocSize(pImage);
PVOID pOptionHeader = NULL;
GetPEOptionHeader(pImage, &pOptionHeader);
//dwRelocTable_FOA为重定位表在文件中的FOA
DWORD dwRelocTable_FOA = RVA_To_FOA(pImage,
((PIMAGE_OPTIONAL_HEADER32)pOptionHeader)->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
memcpy_s(Section_FOA + (char*)pImage, SizeOfBlocks, (char*)pImage + dwRelocTable_FOA, SizeOfBlocks);
ZeroMemory((char*)pImage + dwRelocTable_FOA, SizeOfBlocks);
((PIMAGE_OPTIONAL_HEADER32)pOptionHeader)->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress= FOA_To_RVA(pImage, Section_FOA);
ImageBufferToFile(pImage,"c:/MoveReloc.dll");
}
DWORD GetRelocSize(PVOID pImage)
{
PVOID pOptionHeader = NULL;
GetPEOptionHeader(pImage, &pOptionHeader);
//dwRelocTable_FOA为重定位表在文件中的FOA
DWORD dwRelocTable_FOA = RVA_To_FOA(pImage, ((PIMAGE_OPTIONAL_HEADER32)pOptionHeader)->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
//获取所有块的大小
DWORD SizeOfBlock = 0;
while (*((DWORD*)pImage + dwRelocTable_FOA / 4) != 0 && *((DWORD*)pImage + dwRelocTable_FOA / 4 + 1) != 0)
{
SizeOfBlock += *((DWORD*)pImage + dwRelocTable_FOA / 4 + 1);
dwRelocTable_FOA += *((DWORD*)pImage + dwRelocTable_FOA / 4 + 1);
}
//返回值+8 增加0结尾 遍历重定位表有结束的标志
return SizeOfBlock+8;
}