跳到主要内容

反射式 DLL 注入介绍

反射式 DLL 注入(Reflective DLL Injection)是一种高级的 DLL 注入技术,允许在不使用常规 Windows API(如 LoadLibrary)的情况下,将 DLL 注入到目标进程中并执行。

反射式 DLL 注入的关键在于将 DLL 自身携带的加载器和解析器代码一并注入,从而在目标进程内手动加载 DLL。

原理

反射式 DLL 注入的基本原理是将 DLL 的整个映像(包括代码、数据和加载器代码)注入到目标进程的内存中,并手动解析和加载 DLL。以下是主要步骤:

  1. 准备反射式 DLL:需要对 DLL 进行特殊处理,使其包含自我加载的功能。通常,这是通过在 DLL 中包含加载器代码来实现的。
  2. 分配内存:在目标进程中分配足够的内存,用于存储整个 DLL 映像。
  3. 写入 DLL 映像:将 DLL 映像写入目标进程的内存。
  4. 执行加载器代码:在目标进程中创建一个远程线程,执行注入的 DLL 映像中的加载器代码。加载器代码负责解析 DLL 头、加载依赖项、修复重定位并调用入口点。

示例代码

下面是一个使用反射式 DLL 注入的示例代码。假设我们有一个反射式 DLL,它包含一个名为 ReflectiveLoader 的加载器函数。

反射式 DLL 的代码(ReflectiveDLL.c)

#include <windows.h>

// 定义 ReflectiveLoader 函数
__declspec(dllexport) void ReflectiveLoader() {
// 自我加载的实现代码
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
ReflectiveLoader();
break;
}
return TRUE;
}

注入器代码(ReflectiveInjector.cpp)

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

// 获取目标进程的 PID
DWORD GetProcessId(const char* processName) {
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32);

HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) return 0;

Process32First(hSnapshot, &processEntry);
if (!_stricmp(processEntry.szExeFile, processName)) {
CloseHandle(hSnapshot);
return processEntry.th32ProcessID;
}

while (Process32Next(hSnapshot, &processEntry)) {
if (!_stricmp(processEntry.szExeFile, processName)) {
CloseHandle(hSnapshot);
return processEntry.th32ProcessID;
}
}

CloseHandle(hSnapshot);
return 0;
}

// 反射式 DLL 注入函数
BOOL InjectReflectiveDLL(DWORD processId, const char* dllPath) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (hProcess == NULL) {
printf("OpenProcess failed\n");
return FALSE;
}

// 读取 DLL 文件
HANDLE hFile = CreateFile(dllPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("CreateFile failed\n");
CloseHandle(hProcess);
return FALSE;
}

DWORD fileSize = GetFileSize(hFile, NULL);
BYTE* dllBuffer = new BYTE[fileSize];
DWORD bytesRead;
if (!ReadFile(hFile, dllBuffer, fileSize, &bytesRead, NULL)) {
printf("ReadFile failed\n");
CloseHandle(hFile);
CloseHandle(hProcess);
delete[] dllBuffer;
return FALSE;
}
CloseHandle(hFile);

// 在目标进程中分配内存
LPVOID pRemoteMemory = VirtualAllocEx(hProcess, NULL, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (pRemoteMemory == NULL) {
printf("VirtualAllocEx failed\n");
CloseHandle(hProcess);
delete[] dllBuffer;
return FALSE;
}

// 写入 DLL 映像到目标进程
if (!WriteProcessMemory(hProcess, pRemoteMemory, dllBuffer, fileSize, NULL)) {
printf("WriteProcessMemory failed\n");
VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
delete[] dllBuffer;
return FALSE;
}
delete[] dllBuffer;

// 获取 ReflectiveLoader 的偏移地址
DWORD reflectiveLoaderOffset = 0x1000; // 需要根据实际情况调整

// 创建远程线程执行 ReflectiveLoader
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((BYTE*)pRemoteMemory + reflectiveLoaderOffset), pRemoteMemory, 0, NULL);
if (hThread == NULL) {
printf("CreateRemoteThread failed\n");
VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}

WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);

return TRUE;
}

int main() {
const char* targetProcessName = "target.exe";
const char* dllPath = "path\\to\\reflective.dll";

DWORD processId = GetProcessId(targetProcessName);
if (processId == 0) {
printf("Target process not found\n");
return 1;
}

if (InjectReflectiveDLL(processId, dllPath)) {
printf("DLL injected successfully\n");
} else {
printf("DLL injection failed\n");
}

return 0;
}