重定位表的移动

很笨的方法

(写过才能知道,哪些地方,需要注意,开始想的很简单,就三部,写了 一个多小时!!)

void TestMoveRelocDirectory(LPSTR lpszFile)
{
	/*
	1 新增一个节
	2 把重定位的表 移动到那个节中
	3 更改标志位
	*/
	LPVOID pFileBuffer = NULL;
	pFileBuffer= ReadPEFile(lpszFile);
	if(!pFileBuffer)
	{
		printf("文件读取失败\n");
		return;
	}
	
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader_ADD = NULL;
	PIMAGE_DATA_DIRECTORY DataDirectory=NULL;
	
	//Header信息
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
	pSectionHeader_ADD = pSectionHeader;
	
	//1 判断能否添加节
	DWORD Header_size = pDosHeader->e_lfanew + 4 + 20 + pPEHeader->SizeOfOptionalHeader + pPEHeader->NumberOfSections*40;
	if(pOptionHeader->SizeOfHeaders-Header_size<80)
	{
		printf("没有可用空间填充节表\n");
		free(pFileBuffer);
		return;
	}
	
	printf("空间:%d\n",pOptionHeader->SizeOfHeaders-Header_size);
	

	//添加一个节
	//确定参数
	PIMAGE_SECTION_HEADER pSectionHeader_LAST = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);
	pSectionHeader_ADD=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader_ADD+(pPEHeader->NumberOfSections)*40);
	//="NewSec";
	strcpy((char*)pSectionHeader_ADD->Name,"NewSec");
	pSectionHeader_ADD->Misc.VirtualSize = 0x2000;
	pSectionHeader_ADD->VirtualAddress = pOptionHeader->SizeOfImage;
	pSectionHeader_ADD->SizeOfRawData = 0x2000;
	pSectionHeader_ADD->PointerToRawData = pSectionHeader_LAST->PointerToRawData+pSectionHeader_LAST->SizeOfRawData;
	pSectionHeader_ADD->Characteristics = pSectionHeader->Characteristics;

	//填充0
	LPVOID pSectionEND = (LPVOID)((DWORD)pSectionHeader_ADD+40);
	memset(pSectionEND,0,IMAGE_SIZEOF_SECTION_HEADER);

	
	//修改PE头信息
	pPEHeader->NumberOfSections = pPEHeader->NumberOfSections +1;
	pOptionHeader->SizeOfImage  = pOptionHeader->SizeOfImage+0x2000;

	//写入到文件
	FILE *pOutFile = NULL;	
	//打开文件
	pOutFile = fopen("C://addSec.dll","a+b");
	
	if(!pOutFile)
	{
		printf("无法打开文件EXE文件");
		return;
	}
	//写出第一部分
	printf("length: %x \n ",pSectionHeader_ADD->PointerToRawData+pSectionHeader_ADD->SizeOfRawData);

	size_t writeSize = fwrite(pFileBuffer,pSectionHeader_ADD->PointerToRawData,1,pOutFile);
	printf("WirteSize:%d\n",writeSize);
	//写出第二部分
	LPVOID pNewBuffer=(LPVOID)malloc(0x2000);
	if(pNewBuffer==NULL)
	{
		printf("pNewBuffer分配空间失败\n");
		return;
	}
	memset(pNewBuffer,0,0x2000);
	writeSize = fwrite(pNewBuffer,0x2000,1,pOutFile);
	//关闭文件
	fclose(pOutFile);
	free(pFileBuffer);
	free(pNewBuffer);

	//读入添加好节的文件
	pFileBuffer= ReadPEFile("C://addSec.dll");
	
	//将重定位表的信息,放到最后一个节中
		//Header信息
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
	//最后一个节
	pSectionHeader_ADD=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);

	//定位Directory_Data;
	DataDirectory = pOptionHeader->DataDirectory;
	
	//重定位表

	printf("IMAGE_DIRECTORY_ENTRY_BASERELOC: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
		DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);

	//DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva)
	DWORD FoA = RVAToFileOffset(pFileBuffer,0x2df10);
	
	DWORD BaseReloc_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
	DWORD BaseReloc_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
	FoA = RVAToFileOffset(pFileBuffer,BaseReloc_Directory_Address);
	

	//定位到第一个重定位块
	PIMAGE_BASE_RELOCATION pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA);
	PIMAGE_BASE_RELOCATION pRelocData_Start = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA);

	DWORD sizeOfRelocDirectory = 0;
	//计算重定位表的大小
	while(pRelocData->VirtualAddress||pRelocData->SizeOfBlock)
	{
		DWORD RelocVirtualAddress = pRelocData->VirtualAddress;
		DWORD RelocSize = pRelocData->SizeOfBlock;

		sizeOfRelocDirectory = sizeOfRelocDirectory + RelocSize;

		pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocData + RelocSize);
	}

	//起始位置pRelocData
	
	
	//移动
	PDWORD myRelocLoc = (PDWORD)pSectionHeader_ADD->PointerToRawData;
	printf("Reloc: %x , Size: %x \n",pRelocData,sizeOfRelocDirectory);
	

	//memcpy(myRelocLoc,pRelocData,sizeOfRelocDirectory);
	LPVOID destStart = (LPVOID)((DWORD)pFileBuffer + (DWORD)myRelocLoc);

	printf("pFileBuffer:%x, myRelocLoc: %x \n",pFileBuffer,destStart);

	LPVOID srcStart = (LPVOID)(pRelocData_Start);
	
	memcpy(destStart,srcStart,sizeOfRelocDirectory);
	
	
	//修改重定位表的参数
	DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = FileOffsetToRVA(pFileBuffer,pSectionHeader_ADD->PointerToRawData);

	//写出到dll中
	DWORD FileSize = pSectionHeader_ADD->PointerToRawData + pSectionHeader_ADD->SizeOfRawData;

	WirteToFile(pFileBuffer,FileSize,"C://addNewSec.dll");

}

 

原文链接: 重定位表的移动 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://www.gyarmy.com/post-312.html )

发表评论

0则评论给“重定位表的移动”