滴水逆向三期实践14:移动重定位表

重定位表的移动相比导出表就简单太多了,因为重定位表相当于只有一个大表。统计一下这个“大表”的大小,全部移动到新节就行了。因为是使用下一块 VirtualAddress 和 SizeOfBlock 是否全0 来判断重定位表是否结束的,所以拷贝的时候也把这8字节的全0内容也加上一起拷贝进新节。

 最后修改数据目录中的 VirtualAddress 指向新节 RVA 即可。

代码有详细注释


#include "Currency.h"
#include "windows.h"
#include "stdio.h"

void h3262()		//移动重定位表到新节
{
	char FilePath[] = "CRACKME.EXE";	//CRACKME.EXE        CrackHead.exe     Dll1.dll		R.DLL	LoadDll.dll
	char CopyFilePath[] = "CRACKMEcopy.EXE";	//CRACKMEcopy.EXE       CrackHeadcopy.exe
	LPVOID pFileBuffer = NULL;				//会被函数改变的 函数输出之一
	LPVOID* ppFileBuffer = &pFileBuffer;	//传进函数的形参
	
	int SizeOfFileBuffer;
	int SizeOfNewFileBuffer;
	LPVOID pNewFileBuffer = NULL;
	LPVOID* ppNewFileBuffer = &pNewFileBuffer;

	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_FILE_HEADER pFileHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
	PIMAGE_BASE_RELOCATION pRelocationTable = NULL;
	PIMAGE_SECTION_HEADER pNewSectionHeader = NULL;		//指向最后一个节表的下一个节表,即不存在的节表作为新开辟的节表
	DWORD nameFOA = NULL;
	DWORD AddressOfNamesFOA = NULL;

	SizeOfFileBuffer = ReadPEFile(FilePath, ppFileBuffer);	//pFileBuffer即指向已装载到内存中的exe首部
																/*pFileBuffer = *ppFileBuffer;*/
	if (!SizeOfFileBuffer)
	{
		printf("文件读取失败\n");
		return;
	}
	//Dos头
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;	// 强转 DOS_HEADER 结构体指针
	//可选PE头	  简化后的处理
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuffer + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
	//重定向表
	pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + RVA2FOA(pFileBuffer, pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
	printf("RelocationTable VirtualAddress:%x\n", pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
	if (!pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
	{
		printf("该文件没有重定向表!\n");
		return;
	}
	int i = 1;
	int SizeOfRelocationTable = 0;	//重定向表的大小,单位字节
	while (pRelocationTable->VirtualAddress && pRelocationTable->SizeOfBlock)
	{
		printf("第%d个块VirtualAddress:%x\n", i, pRelocationTable->VirtualAddress);
		printf("第%d个块SizeOfBlock:%x\n", i, pRelocationTable->SizeOfBlock);
		SizeOfRelocationTable += pRelocationTable->SizeOfBlock;
		printf("第%d个块项数:%d\n", i, (pRelocationTable->SizeOfBlock - 8) / 2);
		pRelocationTable = (PIMAGE_BASE_RELOCATION)(pRelocationTable->SizeOfBlock + (DWORD)pRelocationTable);
		i++;
	}
	SizeOfRelocationTable += 8;	//加上最后全0的八字节
	printf("重定位表的大小:%d\n", SizeOfRelocationTable);
	//新增节,可能头抬升,因此全拷贝到pNewFileBuffer,之后上面的寻址得全部来一遍
	SizeOfNewFileBuffer = AddNewSection(pFileBuffer, SizeOfFileBuffer, SizeOfRelocationTable, ppNewFileBuffer);
	//重新对pNewFileBuffer来一遍
	//Dos头
	pDosHeader = (PIMAGE_DOS_HEADER)pNewFileBuffer;	// 强转 DOS_HEADER 结构体指针
	//PE头
	pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNewFileBuffer + pDosHeader->e_lfanew + 4);	//NT头地址 + 4 为 FileHeader 首址
	//可选PE头
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
	//首个节表
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);
	for (int i = 1; i < pFileHeader->NumberOfSections; i++, pSectionHeader++)	//注意这里i从1开始 i < NumberOfSections
	{
	}	//出循环后pSectionHeader指向最后一个节表,也即新的节表
	pNewSectionHeader = pSectionHeader;

	//旧重定向表绝对地址
	pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pNewFileBuffer + RVA2FOA(pNewFileBuffer, pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));

	//拷贝重定位表  新filebuffer头+新节表中的文件偏移 作为拷贝目的地址     旧重定向表绝对地址为拷贝源 
	memcpy(PVOID((DWORD)pNewFileBuffer + pNewSectionHeader->PointerToRawData ), pRelocationTable, SizeOfRelocationTable);
	//修改重定位表的地址值           节头 + 偏移
	pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = pNewSectionHeader->VirtualAddress ;

	//输出测试
	//计算新的重定向表
	pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pNewFileBuffer + RVA2FOA(pNewFileBuffer, pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
	printf("RelocationTable VirtualAddress:%x\n", pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
	if (!pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
	{
		printf("该文件没有重定向表!\n");
		return;
	}
	i = 1;
	while (pRelocationTable->VirtualAddress && pRelocationTable->SizeOfBlock)
	{
		printf("第%d个块VirtualAddress:%x\n", i, pRelocationTable->VirtualAddress);
		printf("第%d个块SizeOfBlock:%x\n", i, pRelocationTable->SizeOfBlock);
		printf("第%d个块项数:%d\n", i, (pRelocationTable->SizeOfBlock - 8) / 2);
		pRelocationTable = (PIMAGE_BASE_RELOCATION)(pRelocationTable->SizeOfBlock + (DWORD)pRelocationTable);
		i++;
	}

	MemeryToFile(pNewFileBuffer, SizeOfNewFileBuffer, CopyFilePath);
	free(pNewFileBuffer);
	free(pFileBuffer);

}



这里最后会再次根据新内存找到新的重定位表,然后打印重定位表内容,看是否和移动前打印的一致。用做一定的移动成功的验证。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值