编译正常但DLL注入无执行效果,求问题排查(附源码)
DLL注入程序无效果排查
我正在学习网络安全,目前接触到DLL注入主题。作为实验,我为一款游戏编写了自定义DLL注入程序,语法与编译均正常,完全按照CreateRemoteThread文档实现,对接DLLMAIN接口,还添加了消息框提示DLL附加成功,但无任何效果。以下是我的源码:
#include <windows.h> #include <tlhelp32.h> #include <stdio.h> BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MessageBoxA(NULL, "Successfully connected to DLL!", "DLL Injector", MB_OK); break; case DLL_THREAD_ATTACH: MessageBoxA(NULL, "it worked", "k", MB_OK); case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } int getProcId(const char* target){ DWORD pID = 0; PROCESSENTRY32 pe32; pe32.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); wchar_t wideTarget[MAX_PATH]; MultiByteToWideChar(CP_UTF8, 0, target, -1, wideTarget, MAX_PATH); do { wchar_t wideExeFile[MAX_PATH]; MultiByteToWideChar(CP_UTF8, 0, pe32.szExeFile, -1, wideExeFile, MAX_PATH); if (wcscmp(wideExeFile, wideTarget) == 0) { CloseHandle(hSnapshot); pID = pe32.th32ProcessID; break; } } while (Process32Next(hSnapshot, &pe32)); CloseHandle(hSnapshot); return pID; } int injectDLL(int pID, const char* dllPath) { HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pID); if (hProcess == NULL) { return 1; } LPVOID pRemotePath = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (pRemotePath == NULL) { CloseHandle(hProcess); return 2; } if (!WriteProcessMemory(hProcess, pRemotePath, dllPath, strlen(dllPath) + 1, NULL)) { VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE); CloseHandle(hProcess); return 3; } HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); FARPROC pLoadLibraryA = GetProcAddress(hKernel32, "LoadLibraryA"); HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibraryA, pRemotePath, 0, NULL); if (hRemoteThread == NULL) { VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE); CloseHandle(hProcess); return 4; } WaitForSingleObject(hRemoteThread, INFINITE); VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE); CloseHandle(hRemoteThread); CloseHandle(hProcess); return 0; } int main(int argc, char* argv[]) { const char* process = "Left 4 dead 2 - Direct3D 9"; const char* dllPath = "Engine.dll"; int pID = getProcId(process); if (pID == 0) { // Process not found return 1; } int result = injectDLL(pID, dllPath); if (result == 0) { printf("success");// Injection succeeded } else { printf("not successful"); // Injection failed } return 0; }
问题排查与修复方案
1. 进程名匹配逻辑错误
你用窗口标题"Left 4 dead 2 - Direct3D 9"匹配进程,但Process32接口获取的szExeFile是可执行文件名(如left4dead2.exe),不是窗口标题。另外原函数的字符串转换逻辑冗余且错误:pe32.szExeFile在Unicode环境下本身就是宽字符,无需转码,直接用宽字符对比即可。
2. DLL路径使用相对路径
注入时目标游戏的工作目录和你的注入程序不一致,LoadLibraryA无法找到相对路径下的Engine.dll,必须传入绝对路径,比如"C:\\Projects\\Engine.dll"。
3. DLLMain调用MessageBox的局限性
很多游戏进程(尤其是带反作弊或特殊UI线程处理的)会阻止非UI线程弹出消息框,或因线程上下文问题导致消息框不显示。建议换成写入日志文件的方式验证DLL是否加载:
FILE* logFile = fopen("C:\\dll_attach_log.txt", "w"); if (logFile) { fprintf(logFile, "DLL attached to process!\n"); fclose(logFile); }
另外原DLLMain中DLL_THREAD_ATTACH分支缺少break,会穿透到后续分支,属于代码瑕疵,建议补上。
4. 权限与架构不匹配
- 注入程序必须以管理员权限运行,否则
OpenProcess可能无法获取足够权限打开目标进程。 - 确保注入程序、DLL、目标游戏三者的CPU架构一致(均为32位或均为64位),架构不匹配会导致
CreateRemoteThread直接失败。
5. 缺失LoadLibrary执行结果检查
原代码仅等待远程线程结束,但未检查LoadLibraryA的返回值,无法确认DLL是否真的被加载。可在WaitForSingleObject后添加:
DWORD exitCode; GetExitCodeThread(hRemoteThread, &exitCode); if (exitCode == NULL) { // LoadLibrary调用失败,返回错误码 VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE); CloseHandle(hRemoteThread); CloseHandle(hProcess); return 5; }
修正后的关键代码示例
修正后的getProcId函数
DWORD getProcId(const wchar_t* targetExe) { DWORD pID = 0; PROCESSENTRY32W pe32; pe32.dwSize = sizeof(PROCESSENTRY32W); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return 0; if (Process32FirstW(hSnapshot, &pe32)) { do { if (wcscmp(pe32.szExeFile, targetExe) == 0) { pID = pe32.th32ProcessID; break; } } while (Process32NextW(hSnapshot, &pe32)); } CloseHandle(hSnapshot); return pID; }
修正后的main函数
int main(int argc, char* argv[]) { const wchar_t* process = L"left4dead2.exe"; const char* dllPath = "C:\\YourFullPath\\Engine.dll"; DWORD pID = getProcId(process); if (pID == 0) { printf("Process not found\n"); return 1; } int result = injectDLL(pID, dllPath); if (result == 0) { printf("Injection initiated successfully\n"); } else { printf("Injection failed with code %d\n", result); } return 0; }
内容的提问来源于stack exchange,提问作者SmoothBrainBoy12
相关产品推荐
相关产品推荐

