PE结构(11)导入表注入DLL

注入原理

修改原PE文件导入表,将自己的Inject Dll追加到导入表中。

从而影响原PE文件加载时的流程,将自身Dll加载至其内存空间。

流程概览

  1. 添加新节,用于将原PE文件整个导入表拷贝
  2. 在拷贝的新表中,追加一个导入项
  3. 添加需要注入的dll名字、函数名字,用以重建INT表和IAT表
  4. 修改原PE结构的数据页目录,将导入表地址RVA指向新表
  5. dump存盘,尝试运行

代码实现

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
void work08() {
//将指定文件加载到内存,并解析PE信息到PEFILE结构体
PEFILE peFile{ 0 };
FILE* pFile = fopen("D:\\1.exe", "rb");

int fileLength = LoadFileToMemory(pFile, &peFile);
int r = fclose(pFile);

if (peFile.h_pe == nullptr) {
return;
}
DWORD bufferImageBase = (DWORD)peFile.h_dos;

//获取导入表
PDATA_IMPORT_DIRECTORY pImportTable = nullptr;
GetImportTable(&pImportTable, &peFile);

//第一步,添加节
lpPETable newTable = (lpPETable)AddSection(&peFile, (char*)".crack", 0x1000);
if (newTable == nullptr) {
return;
}
DWORD index = bufferImageBase + newTable->PointerToRawData;
//设置注入dll的名字
const char* dllName = "TestDLL.dll";
DWORD dllNameFOA = index - bufferImageBase;
DWORD dllNameRVA = Foa2Rva(dllNameFOA, &peFile);
memcpy((LPVOID)index, dllName, strlen(dllName) + 1);
index += strlen(dllName) + 1;

//第二步,拷贝导入表
int importTableIndex = 0;
PDATA_IMPORT_DIRECTORY pNewImportTable = (PDATA_IMPORT_DIRECTORY)index;
while ((pImportTable + importTableIndex)->Characteristics != NULL) {
memcpy(
pNewImportTable + importTableIndex,
pImportTable + importTableIndex,
sizeof(DATA_IMPORT_DIRECTORY)
);
index += sizeof(DATA_IMPORT_DIRECTORY);
importTableIndex++;
}

//第三步,增加新导入表
PDATA_IMPORT_DIRECTORY newImportDirectory = (PDATA_IMPORT_DIRECTORY)index;
index += sizeof(DATA_IMPORT_DIRECTORY);
//添加一段空结构作为结束
memset((LPVOID)index, 0, sizeof(DATA_IMPORT_DIRECTORY));
index += sizeof(DATA_IMPORT_DIRECTORY);

//第四步,增加导入函数名
const char* funcNameStr = "mul";
PDATA_IMPORT_BY_NAME funcName = (PDATA_IMPORT_BY_NAME)index;
DWORD funcNameRVA = Foa2Rva((DWORD)funcName - bufferImageBase, &peFile);
funcName->Hint = 0;
memcpy(funcName->Name, funcNameStr, strlen(funcNameStr) + 1);
index += sizeof(WORD) + strlen(funcNameStr) + 1;

//第五步,增加INT与IAT结构
PDATA_THUNK_DATA lpNewINT = (PDATA_THUNK_DATA)index;
index += sizeof(PDATA_THUNK_DATA);
lpNewINT->AddressOfData = funcNameRVA;
memset((LPVOID)index, 0, sizeof(PDATA_THUNK_DATA));
index += sizeof(PDATA_THUNK_DATA);

PDATA_THUNK_DATA lpNewIAT = (PDATA_THUNK_DATA)index;
index += sizeof(PDATA_THUNK_DATA);
lpNewIAT->AddressOfData = funcNameRVA;
memset((LPVOID)index, 0, sizeof(PDATA_THUNK_DATA));
index += sizeof(PDATA_THUNK_DATA);

//第六步,修复INT与IAT
newImportDirectory->Name = dllNameRVA;
newImportDirectory->OriginalFirstThunk = Foa2Rva((DWORD)lpNewINT - bufferImageBase, &peFile);
newImportDirectory->FirstThunk = Foa2Rva((DWORD)lpNewIAT - bufferImageBase, &peFile);
newImportDirectory->TimeDateStamp = 0;

//第七步,修复数据目录
lpPe_DATA_DIRECTORY lpImportDirectory = &peFile.h_op->DataDirectory[1];
lpImportDirectory->VirtualAddress =
Foa2Rva((DWORD)pNewImportTable - bufferImageBase, &peFile);

pFile = fopen("D:\\2.exe", "wb");
DumpFileBufferToFile(pFile, &peFile);
}

PE结构(11)导入表注入DLL
http://dubhehub.github.io/blogs/2024051114490015619.html
Author
Sin
Posted on
May 11, 2024
Licensed under