PE结构(7)修复重定位表

本篇的理论概述已经在其他文章中给出,此处直接给代码实现。

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() {
//将指定文件加载到内存,并解析PE信息到PEFILE结构体
PEFILE peFile{ 0 };
FILE* pFile = fopen("D:\\TestDLL.dll", "rb");
int fileLength = LoadFileToMemory(pFile, &peFile);
fclose(pFile);

//将ImageBase修改掉
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);

//dump为新文件
//根据内存映像dump到磁盘
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;

//PE属性
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;
}

//拷贝PE头
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));
}

测试结果:


PE结构(7)修复重定位表
http://dubhehub.github.io/blogs/20240506163100318.html
Author
Sin
Posted on
May 6, 2024
Licensed under