本篇的理论概述已经在其他文章中给出,此处直接给代码实现。
PE结构(6)重定位表
代码实现
主入口函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| int main() { PEFILE peFile{ 0 }; FILE* pFile = fopen("D:\\TestDLL.dll", "rb"); int fileLength = LoadFileToMemory(pFile, &peFile); fclose(pFile);
if (peFile.h_op == nullptr) { return -1; } DWORD oldImageBase = peFile.h_op->ImageBase; peFile.h_op->ImageBase = 0x20000000;
PDATA_RELOCATION_DIRECTORY pRelocationTable = nullptr; GetRelocationTable(&pRelocationTable, &peFile); FixedRelocationTable(pRelocationTable, &peFile, oldImageBase);
pFile = fopen("D:\\TestDLL2.dll", "wb"); DumpFileBufferToFile(pFile, &peFile); return 0; }
|
修复函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void FixedRelocationTable(PDATA_RELOCATION_DIRECTORY table, lpPEFILE lpPEFile, DWORD oldImageBase) { DWORD imageBaseOffset = lpPEFile->h_op->ImageBase - oldImageBase; DWORD fileStart = (DWORD)lpPEFile->h_dos;
while (table->VirtualAddress != 0 && table->SizeOfBlock != 0) { DWORD virtualAddress = table->VirtualAddress; DWORD offsetNum = (table->SizeOfBlock - 8) / 2; for (int i = 0; i < offsetNum; i++) { WORD offset = table->TypeOffset[i]; BYTE high4bit = offset >> 12; WORD low12bit = offset & 0x0FFF;
if (high4bit != 3) { continue; }
DWORD targetFOA = Rva2Foa(virtualAddress + low12bit, lpPEFile); DWORD* opNumber = (DWORD*)(fileStart + targetFOA); *opNumber = *opNumber + imageBaseOffset; } table = (PDATA_RELOCATION_DIRECTORY)((DWORD)table + table->SizeOfBlock); } }
|
dump文件buffer函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| void DumpFileBufferToFile(FILE* pFile, lpPEFILE peFile) { fseek(pFile, 0, SEEK_SET); DWORD size = peFile->h_op->SizeOfImage; DWORD bufferImageBase = (DWORD)peFile->h_dos;
lpPEHDOS lpHdos = peFile->h_dos; if (lpHdos == nullptr) { return; } lpPEHPE lpHpe = peFile->h_pe; if (lpHpe == nullptr) { return; } lpPEHOPTIONAL lpHop = peFile->h_op; if (lpHop == nullptr) { return; } lpPETable lpTable = peFile->pet; if (lpTable == nullptr) { return; }
DWORD sizeOfHeader = lpHop->SizeOfHeader; for (int i = 0; i < sizeOfHeader; i++) { BYTE byte = *((LPBYTE)bufferImageBase + i); fputc(byte, pFile); }
WORD numberOfSections = lpHpe->NumberOfSections; for (int num = 0; num < numberOfSections; num++) { lpPETable t = (lpTable + num); DWORD pointerToRawData = t->PointerToRawData; DWORD sizeOfRawData = t->SizeOfRawData;
fseek(pFile, pointerToRawData, SEEK_SET);
for (int i = 0; i < sizeOfRawData; i++) { BYTE byte = *((LPBYTE)bufferImageBase + pointerToRawData + i); fputc(byte, pFile); } } }
|
测试修复效果
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <Windows.h> #include <stdio.h>
int main() { typedef float (*MulFunc)(float, float); MulFunc mul = nullptr;
HMODULE hModule = LoadLibraryA("D:\\TestDLL2.dll"); if (hModule == NULL) { return -1; }
mul = (MulFunc)GetProcAddress(hModule, "mul"); printf("mul result : %.2f", mul(5.0f, 6.0f)); }
|
测试结果:
