• 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
    ",pImageOptionalHeader->DataDirectory[5].VirtualAddress);
    	RVA_TO_FOA(pFileBuffer,pImageOptionalHeader->DataDirectory[5].VirtualAddress,&FOA);
    	printf("pRelocationDirectory_FOA:%x
    ", FOA);
    	
    	pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer+(DWORD)FOA); //定位第一张重定位表 文件中的地址
    	
    	while(pRelocationDirectory->SizeOfBlock && pRelocationDirectory->VirtualAddress){
    		printf("VirtualAddress    :%08X
    ", pRelocationDirectory->VirtualAddress);
    		printf("SizeOfBlock       :%08X
    ", pRelocationDirectory->SizeOfBlock);
    		printf("================= BlockData Start ======================
    ");
    		
    		
    		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]
    "
    					,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);
    }
    
  • 相关阅读:
    PHP关于异常说明
    PHP关于微信授权
    python flask使用方法
    scrcpy启动方法
    ADB shell出现error:device offline提示
    使用Spring框架整合Java Mail
    基于Aspectj表达式配置的Spring AOP
    如何安装和使用Maven
    在Linux系统下安装nginx教程
    了解Maven的基本知识
  • 原文地址:https://www.cnblogs.com/zpchcbd/p/13062311.html
Copyright © 2020-2023  润新知