下面的代码实现:
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);
}