下面的代碼實現:
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);
}
