首页
社区
课程
招聘
[原创]新增节移动重定向表……
发表于: 2018-10-14 01:15 5767

[原创]新增节移动重定向表……

2018-10-14 01:15
5767

移动重定向表

拖了好久了,才重新更……今天被护网杯的CTF劝退之后终于想起来自己有代码没写完……
重定向表不过多介绍了之前的帖子有,https://bbs.pediy.com/thread-246759.htm。
在这里就说一下移动重定向表的步骤吧:
编译工具:VS2013
环境:win7
测试软件:自写DLL

移动重定向表

1.先定位到重定向表,因为给出的是virtuallaaddress,所以需要先把这个地址转成FOA,在文件中先定位。
2.计算重定向表的大小,因为要新增节所以要给节分配大小大小就按照FileAlignment的整数倍分配。
3.新增节。
4.将重定向表的信息移动到新增加的节表的地方。
5.将数据目录项里边的重顶向表的地址改成新增节的首地址,这个地方又需要把pointtoraw转成RVA
6.存盘,搞定。

大体的步骤就是上边的这些,不说废话又到了大家最喜欢的时间,看代码:
VOID MoveRelocation(){
	//定义文件头部的信息
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNtHeaders = NULL;
	PIMAGE_FILE_HEADER pFileHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	PIMAGE_BASE_RELOCATION pRelocation = NULL;


	LPVOID newBuffer;
	LPVOID pFileBuffer = NULL;

	int a = 2;
	//读取文件
	if (!ReadPEFile(INDLLPATH, &pFileBuffer)){
		printf("读取缓冲区失败\n");
		free(pFileBuffer);
	}
	//为每个头赋值
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4);
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
	pDataDirectory = (PIMAGE_DATA_DIRECTORY)((DWORD)pOptionalHeader + 96);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);

	//定位到数据目录项的第六个数据也就是重定向表
	for (size_t i = 0; i < 5; pDataDirectory++, i++);
	DWORD RelocationFOA = 0;

	RelocationFOA = RVATOFOA(pDataDirectory->VirtualAddress, RelocationFOA, pFileBuffer);

	//定位到冲顶向表在文件中的偏移
	pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + RelocationFOA);


	printf("sizeofcode->%x,sizeofdata->%x,sizeofundata->%x", pOptionalHeader->SizeOfCode, pOptionalHeader->SizeOfInitializedData, pOptionalHeader->SizeOfUninitializedData);


	//计数,计算总的重定向表的大小
	DWORD count = 0;
	size_t num = 1;
	for (size_t i = 1; pRelocation->VirtualAddress&&pRelocation->SizeOfBlock; i++){
		count += pRelocation->SizeOfBlock;
		printf("VirtualAddress->%x\tSizeOfBlock->%x\n", pRelocation->VirtualAddress, pRelocation->VirtualAddress);
		pRelocation = (PIMAGE_BASE_RELOCATION)((BYTE*)pRelocation + pRelocation->SizeOfBlock);
		num++;
	}
	printf("重定位表总大小是:%x字节 %x字 %x双字\n,表的数目是:%d\n", count, (count / 2), (count / 4), num);


	//开始重新分配空间
	DWORD size = 0;				//加上重定位表以后的内存的总大小
	DWORD SectionOneFoA = 0;
	DWORD FOA = 0;

	//节里边的pointertorawdata 可以计算出整个的大小

	//定位到最后一个节
	for (size_t i = 1; i < pFileHeader->NumberOfSections ; i++, pSectionHeader++)
	{
		printf("%s\n", pSectionHeader->Name);
	};

	printf("%s\t%x\t%x\n", pSectionHeader->Name, pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData);


	//计算出该申请空间的大小  如果重定向表的大小小于文件对齐的大小那么加上文件对齐的大小
	DWORD FileAlignment = pOptionalHeader->FileAlignment;
	/*int a = 0;
	int j = 0;
	for (size_t i = 0; count>FileAlignment; i++)
	{
		FileAlignment = FileAlignment*a;
		a++;
	}
	printf("需要%x个文件对齐的空间才能保存重定位表,重定位表大小为%x,文件对齐大小为%x\n", a, count, FileAlignment);
	*/

	size = pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData + FileAlignment;
	pOptionalHeader->SizeOfImage += 0x400;
	printf("内存总大小:%x\n", size);
	//将节表移动到第一个节表
	for (size_t i = 1; i < pFileHeader->NumberOfSections ; i++, pSectionHeader--)
	{
		printf("%s\n", pSectionHeader->Name);
	}
	printf("%s\n", pSectionHeader->Name);

	newBuffer = malloc(size);
	if (!newBuffer){
		printf("内存申请失败\n");
		free(newBuffer);
		free(pFileBuffer);
		return;
	}


	memset(newBuffer, 0, size);
	//复制头
	memcpy(newBuffer, pFileBuffer, pOptionalHeader->SizeOfHeaders);
	//复制节表  

	PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;

	for (size_t i = 1; i < pFileHeader->NumberOfSections; i++, pSectionHeader++, pTempSectionHeader++)
	{
		//memcpy异常!有错误
		memcpy((void*)((DWORD)newBuffer + pTempSectionHeader->PointerToRawData),
			(void*)((DWORD)pFileHeader + pSectionHeader->PointerToRawData),
			pSectionHeader->SizeOfRawData);
		printf("%s\t", pTempSectionHeader->Name);
	}
	//将原始节表指针移动到初始位置
	for (size_t i = 0; i < pFileHeader->NumberOfSections; i++, pSectionHeader--);
	printf("%s\n",pSectionHeader->Name);
	/***************************************************************/
	//为新的内存空间的属性的节更改数据

	PIMAGE_DOS_HEADER pNewDosHeader = NULL;
	PIMAGE_NT_HEADERS pNewNtHeaders = NULL;
	PIMAGE_FILE_HEADER pNewFileHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pNewOptionalHeader = NULL;
	PIMAGE_SECTION_HEADER pNewSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pNewDataDirectory = NULL;
	PIMAGE_BASE_RELOCATION pNewRelocation = NULL;

	pNewDosHeader = (PIMAGE_DOS_HEADER)newBuffer;
	pNewNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)newBuffer + pNewDosHeader->e_lfanew);
	pNewFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNewNtHeaders + 4);
	pNewOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pNewFileHeader + IMAGE_SIZEOF_FILE_HEADER);
	pNewDataDirectory = (PIMAGE_DATA_DIRECTORY)((DWORD)pNewOptionalHeader + 96);
	pNewSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNewOptionalHeader + pNewFileHeader->SizeOfOptionalHeader);


	/***************************************************************/
	printf("最后一个节的结尾地址是:%x\n", (pTempSectionHeader->PointerToRawData + pTempSectionHeader->SizeOfRawData));
	//新添加一个节,然后移动重定位表,先将重定位表移动过来,然后再将原来的重定位表清零  全部填充为00

	//新增节
	printf("原节表数目为%d\n", pNewFileHeader->NumberOfSections);
	pNewFileHeader->NumberOfSections++;

	printf("节表数目%d\n", pNewFileHeader->NumberOfSections);

	
	//定位到新增的节表的位置
	/*pNewSectionHeader-》1              1,2,3,4,5,6,7,8*/
	for (size_t i = 0; i < pNewFileHeader->NumberOfSections-1; i++, pNewSectionHeader++);

	//为新节表复制
	pNewSectionHeader->Characteristics = 0x20000060;
	pNewSectionHeader->NumberOfLinenumbers = 0;
	pNewSectionHeader->NumberOfRelocations = 0;
	pNewSectionHeader->PointerToRawData = 0x7600;
	pNewSectionHeader->PointerToRelocations = 0;
	pNewSectionHeader->SizeOfRawData = 0x400;
	//VirtualAddress 的大小是上一个节的virtualAddress+virtualsize
	pNewSectionHeader->VirtualAddress = pTempSectionHeader->VirtualAddress + pTempSectionHeader->Misc.VirtualSize;
	pNewSectionHeader->Misc.VirtualSize = pNewOptionalHeader->SectionAlignment ;
	pNewSectionHeader->Name[0] = '.';
	pNewSectionHeader->Name[1] = 'n';
	pNewSectionHeader->Name[2] = 'e';
	pNewSectionHeader->Name[3] = 'w';


	//将重定位表的数据移动到新的内存空间 然后memcpy到新增的节表处  先修改完virtualAddress


	//移动到最后一个节表
	
	for (size_t i = 0; i < 5; i++, pNewDataDirectory++);
	pNewDataDirectory->VirtualAddress = pNewSectionHeader->VirtualAddress+pNewSectionHeader->Misc.VirtualSize;   //这是文件地址
	
	//根据重定位表的大小分配空间
	LPVOID Relocation = NULL;
	Relocation = malloc(a*pOptionalHeader->FileAlignment);    
	memset(Relocation, 0, a*pOptionalHeader->FileAlignment);
	//将重定位表的文件地址开始的地方复制到新的节表的文件地址开始的地方

	memcpy((void*)(pNewSectionHeader->PointerToRawData), ((void*)((DWORD)pFileBuffer + RelocationFOA)), 0x320);

//	memcpy((void*)pNewSectionHeader->PointerToRawData, Relocation, pOptionalHeader->FileAlignment*a);
	size_t size_ = 0;
	size_ = (pNewSectionHeader->PointerToRawData + pNewSectionHeader->SizeOfRawData);
	SaveFile(newBuffer, size_, OUTFILEPATH);
	free(pFileBuffer);
	free(Relocation);
	free(newBuffer);
}


这次的代码比较长,而且比较乱,并且还很恶心……
另外有木有做CTF的同学啊,可以交流交流,我之前是 做破解的,很少追码拿flag……

1.先定位到重定向表,因为给出的是virtuallaaddress,所以需要先把这个地址转成FOA,在文件中先定位。
2.计算重定向表的大小,因为要新增节所以要给节分配大小大小就按照FileAlignment的整数倍分配。
3.新增节。
4.将重定向表的信息移动到新增加的节表的地方。
5.将数据目录项里边的重顶向表的地址改成新增节的首地址,这个地方又需要把pointtoraw转成RVA

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (4)
雪    币: 44153
活跃值: (20195)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
ReloX 工具不知有没有看过?通过比较不同其址的Dump文件,重构一份重定位表

https://tools.pediy.com/win/PE_tools/relocations/Relox/ucfrlx10a.zip
2018-10-14 09:25
0
雪    币: 2046
活跃值: (265)
能力值: ( LV7,RANK:104 )
在线值:
发帖
回帖
粉丝
3
kanxue ReloX 工具不知有没有看过?通过比较不同其址的Dump文件,重构一份重定位表 https://tools.pediy.com/win/PE_tools/relocations/Relox/u ...
没看过,还是小白一个
2018-10-14 15:18
0
雪    币: 26036
活跃值: (1409)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
ilyzqe 没看过,还是小白一个
Relox是修复定位表的工具——主要是用于对dll脱壳定位,通过比较不同地址的dump文件进行确定重定位表。

网上有传这个——ReloX修复DLL脱壳重定位表工具集合:Dll_LoadEx+ReloX+EdrTest

还有看雪的教程:ReloX修复DLL脱壳重定位表的简便方法——用Ollydbg手脱Neolite加壳的DLL版
最后于 2018-10-21 00:39 被挽梦雪舞编辑 ,原因:
2018-10-21 00:36
0
雪    币: 291
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
学长能不能写一下移动导出表哈?好难啊,我自己写不出来
2019-6-28 08:13
0
游客
登录 | 注册 方可回帖
返回
//