PE 移動/修復重定位表


下面的代碼實現:

1、先移動了重定位表
2、然后修改重定位表結構指向移動后的重定位的地址
3、接着手動Imagebase自增1000
4、最后修復重定位表

重定位表的作用就是:當實際加載到內存中的Imagebase與本該加載時候的Imagebase地址不同的時候 就需要進行修復重定位表

其實重定位表中存的是需要修改的函數的地址偏移

void MoveRelocationTable(PVOID pFileBuffer, PDWORD OldBufferSize,PVOID* pNewBuffer){
	PIMAGE_DOS_HEADER pImageDosHeader = NULL;
	PIMAGE_FILE_HEADER pImageFileHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pImageOptionalHeader = NULL;
	PIMAGE_SECTION_HEADER pImageSectionHeaderGroup = NULL;
	PIMAGE_SECTION_HEADER NewSec = NULL;
	PIMAGE_BASE_RELOCATION pRelocationDirectory = NULL;
	
	DWORD isOk;
	DWORD NewLength=0;
	PVOID LastSection = NULL;
	PVOID CodeSection = NULL;
	PVOID AddressOfSectionTable = NULL;
	PVOID pTemp;

	DWORD AllSizeOfBlock = 0;
	DWORD RVA = 0;
	DWORD FOA = 0;

	int NumberOfRelocation=0;
	PWORD Location = NULL;
	int i = 0;
	DWORD RVA_Data;
	WORD reloData;



	pImageDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4);
	pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER));
	pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader);
	
	//判斷是否可以容納相應的節表
	isOk = (DWORD)pImageOptionalHeader->SizeOfHeaders - ((DWORD)pImageDosHeader->e_lfanew + IMAGE_SIZEOF_FILE_HEADER + pImageFileHeader->SizeOfOptionalHeader + 40*pImageFileHeader->NumberOfSections);
	if(isOk < 80){
		printf("空間太小 無法進行添加!");
		return;
	}
	
	//生成對應的內存大小的空間
	NewLength += *OldBufferSize + 0x1000;
	*pNewBuffer = (PVOID)malloc(NewLength);
	ZeroMemory(*pNewBuffer,NewLength);
	
	//拷貝之前內存空間 到 當前新生成的內存空間
	memcpy(*pNewBuffer,pFileBuffer,*OldBufferSize);
	
	//獲取新的結構體
	pImageDosHeader = (PIMAGE_DOS_HEADER)(*pNewBuffer);
	pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4);
	pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER));
	pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader);
	
	// pImageFileHeader->NumberOfSections修改
	pImageFileHeader->NumberOfSections = pImageFileHeader->NumberOfSections + 1;
	
	// pImageOptionalHeader->SizeOfImage修改
	pImageOptionalHeader->SizeOfImage = (DWORD)pImageOptionalHeader->SizeOfImage + 0x1000;
	
	// 復制代碼段的節數據到 當前最后一個節數據后面
	CodeSection = (PVOID)(&pImageSectionHeaderGroup[0]);
	
	
	LastSection = (PVOID)(DWORD)(&pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1]);
	memcpy(LastSection,CodeSection,40);
	
	//修正相關屬性
	NewSec = (PIMAGE_SECTION_HEADER)LastSection;
	strcpy(NewSec,".NewSec");
	NewSec->Misc.VirtualSize = 0x1000;
	NewSec->SizeOfRawData = 0x1000;
	NewSec->VirtualAddress = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].VirtualAddress + pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].SizeOfRawData;
	NewSec->PointerToRawData = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].PointerToRawData + pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].SizeOfRawData;
	*OldBufferSize = NewLength;

	//到這里新增節已經完成了
	AddressOfSectionTable = (PVOID)((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData);
	
	//printf("%x",AddressOfSectionTable);

	//重定位表的FOA
	RVA_TO_FOA(*pNewBuffer,pImageOptionalHeader->DataDirectory[5].VirtualAddress,&FOA);
	
	//獲取結構
	pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)*pNewBuffer + FOA);

	pTemp = pRelocationDirectory;
	
	//printf("%x",pRelocationDirectory->VirtualAddress);
	
	//獲取重定位表大小
	while(pRelocationDirectory->SizeOfBlock && pRelocationDirectory->VirtualAddress){
		AllSizeOfBlock = pRelocationDirectory->SizeOfBlock;
		pRelocationDirectory = ((DWORD)pRelocationDirectory + (DWORD)pRelocationDirectory->SizeOfBlock);
	}
	
	//復制重定位表到新增的節數據中
	memcpy(AddressOfSectionTable,pTemp,AllSizeOfBlock);

	//將PE可選頭中的重定位的地址指向新增節數據的起始地址
	pImageOptionalHeader->DataDirectory[5].VirtualAddress = (DWORD)AddressOfSectionTable;

	
	//修改DLL的ImageBase	
	//pImageOptionalHeader->ImageBase += 1000;

	//=============================================================
	//=============================================================
	//=============================================================
	//=============================================================

		
	printf("pRelocationDirectory_RVA:%x\n",pImageOptionalHeader->DataDirectory[5].VirtualAddress);
	RVA_TO_FOA(pFileBuffer,pImageOptionalHeader->DataDirectory[5].VirtualAddress,&FOA);
	printf("pRelocationDirectory_FOA:%x\n", FOA);
	
	pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer+(DWORD)FOA); //定位第一張重定位表 文件中的地址
	
	while(pRelocationDirectory->SizeOfBlock && pRelocationDirectory->VirtualAddress){
		printf("VirtualAddress    :%08X\n", pRelocationDirectory->VirtualAddress);
		printf("SizeOfBlock       :%08X\n", pRelocationDirectory->SizeOfBlock);
		printf("================= BlockData Start ======================\n");
		
		
		NumberOfRelocation = (pRelocationDirectory->SizeOfBlock - 8)/2;// 每個重定位塊中的數據項的數量
		
		Location = (PWORD)((DWORD)pRelocationDirectory + 8); // 加上8個字節
		
		for(i=0;i<NumberOfRelocation;i++){
			if(Location[i] >> 12 != 0){ //判斷是否是垃圾數據
				// WORD類型的變量進行接收
				reloData = (Location[i] & 0xFFF); //這里進行與操作 只取4字節 二進制的后12位
				RVA_Data = pRelocationDirectory->VirtualAddress + reloData; //這個是RVA的地址
				RVA_TO_FOA(pFileBuffer,RVA_Data,&FOA);
				printf("第[%04X]項  數據項的數據為:[%04X]  數據屬性為:[%X]  RVA的地址為:[%08X]  重定位的數據:[%08X]\n"
					,i+1
					,reloData
					,(Location[i] >> 12)
					,RVA_Data
					,*(PDWORD)((DWORD)pFileBuffer+(DWORD)FOA));

				//這里是自增的 進行修復重定位,上面的imagebase我們自增了1000,那么要修復的地址都需要自增1000
				*(PDWORD)((DWORD)pFileBuffer+(DWORD)FOA) = *(PDWORD)((DWORD)pFileBuffer+(DWORD)FOA) + 1000;				
			}
		}
		pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocationDirectory + (DWORD)pRelocationDirectory->SizeOfBlock); //上面的for循環完成之后,跳轉到下個重定位塊 繼續如上的操作
	}

	//=============================================================
	//=============================================================
	//=============================================================
	//=============================================================
	//保存文件
	MyWriteFile(*pNewBuffer,NewLength);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM