C/C++ 实现DLL注入原理详解 含完整代码
本文介绍了Windows平台下使用LoadLibraryW和CreateRemoteThread实现DLL注入的原理与方法。通过CreateRemoteThread在目标进程创建线程,调用LoadLibraryW函数加载指定DLL,关键步骤包括:在目标进程分配内存写入DLL路径、获取LoadLibraryW地址、创建远程线程执行注入。文中提供了完整的注入器代码示例和测试DLL实现,成功注入后DLL
原理
LoadLibraryW
LoadLibraryW函数用于将指定模块加载到调用者进程,函数原型如下
HMODULE
WINAPI
LoadLibraryW(
_In_ LPCWSTR lpLibFileName
);
CreateRemoteThread
CreateRemoteThread函数用于在指定进程创建远程线程,并且可以指定起始地址和参数等,函数原型如下:
HANDLE
WINAPI
CreateRemoteThread(
_In_ HANDLE hProcess,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
注入过程分析
了解了以上两个函数以后,可以发现:用于实现DLL加载的函数LoadLibraryW需要一个DLL路径作为参数,而CreateRemoteThread又正好可以在其他进程的指定地址处创建一个线程,并且附带一个参数。那么,我们是否可以在注入器进程调用CreateRemoteThread,指定在目标进程的LoadLibraryW函数处创建线程,并且附带一个地址作为参数,该地址是我们要注入的DLL的路径,这样,目标进程就会以DLL路径为参数调用LoadLibraryW
注意,CreateRemoteThread附带的参数(DLL路径的地址)必须是目标进程空间的地址。因为我们是在目标进程创建线程,因此该线程只能访问目标进程的数据,也就是说,我们通过创建远程线程在目标进程调用LoadLibraryW的时候,传递的参数(DLL路径的地址)对于目标进程必须是一个有效的地址,该地址存储的是DLL路径。因此,我们需要提前将DLL的路径写到目标进程中。我们需要在目标内存分配一块内存并写入DLL路径,这可以通过VirtualAllocEx和WriteProcessMemory实现
完整代码
理清了思路,现在开始写代码。
为了突出核心原理,本文默认每个函数都成功执行,没有提供非必要的错误校验,读者可自行添加
注入器
#include <Windows.h>
#include <tlhelp32.h>
#include <iostream>
// 替换为你的目标进程ID
DWORD targetProcessId = 0;
// 替换为你的DLL路径
LPCWSTR dllPath = L"D:\\KrnlsYs.dll";
int main()
{
// 获取目标进程的句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcessId);
// 分配内存以存储DLL路径
PVOID targetPathBuffer = VirtualAllocEx(
hProcess,
0,
(lstrlenW(dllPath)+1) * sizeof(WCHAR),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
// 将DLL路径写入目标进程的内存
WriteProcessMemory(hProcess,
targetPathBuffer,
dllPath,
(lstrlenW(dllPath) + 1) * sizeof(WCHAR),
nullptr
);
// 创建远程线程以加载DLL
HANDLE hThread=CreateRemoteThread(hProcess,
nullptr,
0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"),
targetPathBuffer,
0,
nullptr
);
// 等待远程线程完成
WaitForSingleObject(hThread, INFINITE);
// 清理所有资源
CloseHandle(hThread);
VirtualFreeEx(hProcess, targetPathBuffer, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 0;
}
示例DLL
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxW(0, L"Hello KrnlsYs.dll", L"Msg:", 0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
测试运行
测试前请注意:
- 修改注入器的targetProcessId和dllPath变量,以正确设置你的目标进程和DLL
- 以管理员身份运行注入器
测试结果:成功注入

更多推荐



所有评论(0)