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

如何调用已被其他进程加载的DLL中的函数,求可行实现示例

方案1:使用CreateRemoteThread实现跨进程调用DLL导出函数

该方案前提:目标进程与调用程序架构一致(同为32位或64位)、目标进程已加载目标DLL、调用程序持有目标进程的足够操作权限
编译时需要链接psapi.lib库

#include <windows.h>
#include <psapi.h>
#include <iostream>

int main()
{
    // 替换为实际目标进程ID
    DWORD dwPid = 1234;
    // 替换为实际DLL文件名
    const wchar_t* dllName = L"TestDll.dll";
    
    // 1. 打开目标进程
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
    if (!hProcess) {
        std::cout << "打开进程失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    // 2. 计算Test函数的内存偏移
    HMODULE hLocalDll = LoadLibraryW(dllName);
    if (!hLocalDll) {
        std::cout << "本地加载DLL失败,错误码:" << GetLastError() << std::endl;
        CloseHandle(hProcess);
        return 1;
    }
    FARPROC pfnTestLocal = GetProcAddress(hLocalDll, "Test");
    if (!pfnTestLocal) {
        std::cout << "获取Test函数地址失败,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hLocalDll);
        CloseHandle(hProcess);
        return 1;
    }
    uintptr_t testOffset = (uintptr_t)pfnTestLocal - (uintptr_t)hLocalDll;
    FreeLibrary(hLocalDll);

    // 3. 枚举目标进程模块获取DLL基址
    HMODULE hMods[1024];
    DWORD cbNeeded;
    if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
        for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
            WCHAR szModName[MAX_PATH];
            if (GetModuleBaseNameW(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(WCHAR))) {
                if (_wcsicmp(szModName, dllName) == 0) {
                    // 计算Test函数在目标进程的实际地址
                    uintptr_t pfnTestRemote = (uintptr_t)hMods[i] + testOffset;
                    // 4. 创建远程线程执行Test函数
                    HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pfnTestRemote, NULL, 0, NULL);
                    if (hRemoteThread) {
                        WaitForSingleObject(hRemoteThread, INFINITE);
                        CloseHandle(hRemoteThread);
                        std::cout << "远程调用成功,可通过DebugView查看目标进程输出" << std::endl;
                    } else {
                        std::cout << "创建远程线程失败,错误码:" << GetLastError() << std::endl;
                    }
                    break;
                }
            }
        }
    }

    CloseHandle(hProcess);
    return 0;
}

注意:该方案调用后Test函数返回的字符串指针属于目标进程地址空间,调用方无法直接读取,如需获取返回值需要额外做远程内存读取操作


方案2:使用命名管道实现IPC调用

该方案稳定性更高,不会触发安全软件误拦截,可直接获取返回值,也支持跨架构调用。需要将服务端逻辑集成到目标DLL中,随DLL加载启动。

服务端代码(集成到目标DLL)

// 管道服务线程函数
DWORD WINAPI PipeServerThread(LPVOID lpParam)
{
    HANDLE hPipe = CreateNamedPipeW(
        L"\\\\.\\pipe\\TestDllPipe",
        PIPE_ACCESS_DUPLEX,
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
        1,
        1024,
        1024,
        0,
        NULL
    );
    if (hPipe == INVALID_HANDLE_VALUE) {
        return 1;
    }

    while (true) {
        // 等待客户端连接
        if (ConnectNamedPipe(hPipe, NULL)) {
            WCHAR recvBuf[256];
            DWORD dwRead;
            if (ReadFile(hPipe, recvBuf, sizeof(recvBuf), &dwRead, NULL)) {
                // 约定收到CallTest指令则执行Test函数
                if (wcscmp(recvBuf, L"CallTest") == 0) {
                    LPCWSTR result = Test();
                    DWORD dwWritten;
                    WriteFile(hPipe, result, (wcslen(result) + 1) * sizeof(WCHAR), &dwWritten, NULL);
                }
            }
            DisconnectNamedPipe(hPipe);
        }
    }
    CloseHandle(hPipe);
    return 0;
}

// 修改DllMain的DLL_PROCESS_ATTACH分支,加载DLL时启动服务线程
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugStringW(L"Loading Library...");
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, 0, PipeServerThread, NULL, 0, NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

客户端代码(发起调用的程序)

#include <windows.h>
#include <iostream>

int main()
{
    HANDLE hPipe = CreateFileW(
        L"\\\\.\\pipe\\TestDllPipe",
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
    );
    if (hPipe == INVALID_HANDLE_VALUE) {
        std::cout << "连接管道失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    // 发送调用请求
    const WCHAR* req = L"CallTest";
    DWORD dwWritten;
    WriteFile(hPipe, req, (wcslen(req) + 1) * sizeof(WCHAR), &dwWritten, NULL);

    // 读取返回结果
    WCHAR resp[256];
    DWORD dwRead;
    ReadFile(hPipe, resp, sizeof(resp), &dwRead, NULL);
    std::wcout << L"调用Test返回结果:" << resp << std::endl;

    CloseHandle(hPipe);
    return 0;
}

内容的提问来源于stack exchange,提问作者user16839617

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:54:05