You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译正常但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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 09:23:10