重定位表

本文深入探讨了PE文件格式中重定位表的结构和工作原理,详细讲解了如何从数据目录表中获取重定位表的位置,解析每个block的virtualAddress和大小,以及如何通过修改重定位表实现imagebase的变更。同时,介绍了移动重定位表的方法,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
位于数据目录表的第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;
}
		

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值