开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1308|回复: 24
收起左侧

[易语言纯源码] 易语言调用64位dll

[复制链接]
结帖率:0% (0/1)
发表于 2024-10-22 17:12:08 | 显示全部楼层 |阅读模式   上海市上海市
分享源码
界面截图:
是否带模块: -
备注说明: -
最近要搞这个,所以,弄了个C++实现了下调用64位dll,前提是这个64位dll函数公开啊,不公开的用其他大神的模块或者工具,汇编啥的整不来。
这个设计主要涉及两个组件:32位的 Bridge32.dll 和 64位的 Helper64.exe。让我们逐步分析这个调用过程:
初始化阶段:
当 Bridge32.dll 被加载时(通常是在 DLL_PROCESS_ATTACH),它会启动 Helper64.exe。
Helper64.exe 启动后会创建一个命名管道,等待来自 Bridge32.dll 的连接。
调用过程:
当 32位应用程序调用 Bridge32.dll 中的 CallFunction 时,以下步骤会发生:
a. Bridge32.dll 连接到 Helper64.exe 创建的命名管道。
b. Bridge32.dll 将调用信息(DLL名称、函数名、参数)通过管道发送给 Helper64.exe。
c. Helper64.exe 接收这些信息,然后动态加载指定的 64位 DLL。
d. Helper64.exe 使用 GetProcAddress 获取指定函数的地址。
e. Helper64.exe 调用该函数,并获取返回值。
f. Helper64.exe 将返回值通过管道发送回 Bridge32.dll。
g. Bridge32.dll 接收结果并返回给调用它的 32位应用程序。
通信机制:
使用命名管道进行 32位和 64位进程间的通信。
命名管道允许双向通信,适合请求-响应模型。
4. 动态加载:
Helper64.exe 使用 LoadLibrary 动态加载 64位 DLL。
使用 GetProcAddress 获取函数地址,允许调用未在编译时链接的函数。

[C++] 纯文本查看 复制代码
#include <windows.h>
#include <string>
#include <sstream>
#include <map>

#define PIPE_NAME "\\\\.\\pipe\\UniversalBridge64Pipe"
#define SHUTDOWN_EVENT_NAME "Global\\Helper64ShutdownEvent"

typedef int(__stdcall* GENERICFUNCTION)();

std::map<std::string, HMODULE> loadedDlls;

HMODULE LoadDLL(const std::string& dllName) {
    if (loadedDlls.find(dllName) == loadedDlls.end()) {
        HMODULE hDll = LoadLibraryA(dllName.c_str());
        if (hDll) {
            loadedDlls[dllName] = hDll;
        }
        return hDll;
    }
    return loadedDlls[dllName];
}

std::string CallFunction(const std::string& dllName, const std::string& funcName, const std::string& args) {
    HMODULE hDll = LoadDLL(dllName);
    if (!hDll) {
        return "ERROR: Failed to load DLL";
    }

    FARPROC func = GetProcAddress(hDll, funcName.c_str());
    if (!func) {
        return "ERROR: Failed to find function";
    }

    if (funcName == "GetNetworkAdapterInfo") {
        typedef const char* (__stdcall* GetNetworkAdapterInfoFunc)(int);
        GetNetworkAdapterInfoFunc getNetworkAdapterInfo = reinterpret_cast<GetNetworkAdapterInfoFunc>(func);
        int index = std::stoi(args);
        const char* result = getNetworkAdapterInfo(index);
        return result ? result : "ERROR: Null result";
    }
    else if (funcName == "GetActiveNetworkAdapterInfo") {
        typedef const char* (__stdcall* GetActiveNetworkAdapterInfoFunc)();
        GetActiveNetworkAdapterInfoFunc getActiveNetworkAdapterInfo = reinterpret_cast<GetActiveNetworkAdapterInfoFunc>(func);
        const char* result = getActiveNetworkAdapterInfo();
        return result ? result : "ERROR: Null result";
    }
    else {
        int result = reinterpret_cast<int(*)()>(func)();
        return std::to_string(result);
    }
}

DWORD WINAPI MonitorParentProcess(LPVOID lpParam) {
    const char* parentProcessIdStr = static_cast<const char*>(lpParam);
    DWORD parentProcessId = strtoul(parentProcessIdStr, NULL, 10);

    HANDLE hParentProcess = OpenProcess(SYNCHRONIZE, FALSE, parentProcessId);
    if (hParentProcess == NULL) {
        return 1;
    }

    WaitForSingleObject(hParentProcess, INFINITE);

    CloseHandle(hParentProcess);

    HANDLE hShutdownEvent = OpenEventA(EVENT_MODIFY_STATE, FALSE, SHUTDOWN_EVENT_NAME);
    if (hShutdownEvent != NULL) {
        SetEvent(hShutdownEvent);
        CloseHandle(hShutdownEvent);
    }

    return 0;
}

DWORD WINAPI ClientHandler(LPVOID lpParam) {
    HANDLE hPipe = (HANDLE)lpParam;
    char buffer[1024];
    DWORD bytesRead;

    if (ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL)) {
        buffer[bytesRead] = '\0';
        std::string input(buffer);
        std::istringstream iss(input);
        std::string dllName, funcName, args;
        std::getline(iss, dllName, '|');
        std::getline(iss, funcName, '|');
        std::getline(iss, args);

        std::string result = CallFunction(dllName, funcName, args);
        DWORD bytesWritten;
        WriteFile(hPipe, result.c_str(), static_cast<DWORD>(result.length()), &bytesWritten, NULL);

        FlushFileBuffers(hPipe);
    }

    CloseHandle(hPipe);
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    if (__argc <= 1) {
        return 1;
    }

    const char* parentProcessIdStr = __argv[1];

    HANDLE hMonitorThread = CreateThread(NULL, 0, MonitorParentProcess, (LPVOID)parentProcessIdStr, 0, NULL);
    if (hMonitorThread == NULL) {
        return 1;
    }

    HANDLE hShutdownEvent = CreateEventA(NULL, TRUE, FALSE, SHUTDOWN_EVENT_NAME);
    if (hShutdownEvent == NULL) {
        return 1;
    }

    while (true) {
        HANDLE hPipe = CreateNamedPipeA(
            PIPE_NAME,
            PIPE_ACCESS_DUPLEX,
            PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
            PIPE_UNLIMITED_INSTANCES,
            1024,
            1024,
            0,
            NULL
        );

        if (hPipe == INVALID_HANDLE_VALUE) {
            Sleep(1000);
            continue;
        }

        HANDLE waitHandles[2] = { hShutdownEvent, hPipe };
        DWORD waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);

        if (waitResult == WAIT_OBJECT_0) {
            CloseHandle(hPipe);
            break;
        }

        if (waitResult == WAIT_OBJECT_0 + 1) {
            BOOL connected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
            if (connected) {
                HANDLE hThread = CreateThread(NULL, 0, ClientHandler, (LPVOID)hPipe, 0, NULL);
                if (hThread == NULL) {
                    CloseHandle(hPipe);
                }
                else {
                    CloseHandle(hThread);
                }
            }
            else {
                CloseHandle(hPipe);
            }
        }
    }

    CloseHandle(hShutdownEvent);

    WaitForSingleObject(hMonitorThread, INFINITE);
    CloseHandle(hMonitorThread);

    for (auto& dll : loadedDlls) {
        FreeLibrary(dll.second);
    }
    return 0;
}
[C++] 纯文本查看 复制代码
#include <windows.h>
#include <string>
#include <thread>
#include <chrono>

#define PIPE_NAME "\\\\.\\pipe\\UniversalBridge64Pipe"
#define SHUTDOWN_EVENT_NAME "Global\\Helper64ShutdownEvent"

HANDLE g_hHelper = NULL;

void StartHelper() {
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    DWORD parentProcessId = GetCurrentProcessId();
    std::string parentProcessIdStr = std::to_string(parentProcessId);

    std::string cmdLine = "Helper64.exe " + parentProcessIdStr;

    if (CreateProcessA(NULL, const_cast<char*>(cmdLine.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        CloseHandle(pi.hThread);
        g_hHelper = pi.hProcess;
    }
}

bool EnsureHelperRunning() {
    if (g_hHelper == NULL || WaitForSingleObject(g_hHelper, 0) == WAIT_OBJECT_0) {
        StartHelper();
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
    return g_hHelper != NULL;
}

extern "C" __declspec(dllexport) const char* __stdcall CallFunction(const char* dllName, const char* funcName, const char* params)
{
    static char resultBuffer[1024] = { 0 };

    for (int retry = 0; retry < 3; retry++) {
        if (!EnsureHelperRunning()) {
            strcpy_s(resultBuffer, "ERROR: Helper not running");
            return resultBuffer;
        }

        HANDLE hPipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (hPipe == INVALID_HANDLE_VALUE) {
            if (retry == 2) {
                strcpy_s(resultBuffer, "ERROR: Failed to connect to pipe after 3 attempts");
                return resultBuffer;
            }
            Sleep(100);
            continue;
        }

        std::string message = std::string(dllName) + "|" + funcName + "|" + (params ? params : "");

        DWORD bytesWritten;
        if (!WriteFile(hPipe, message.c_str(), static_cast<DWORD>(message.length()), &bytesWritten, NULL) || bytesWritten != message.length()) {
            CloseHandle(hPipe);
            if (retry == 2) {
                strcpy_s(resultBuffer, "ERROR: Failed to write to pipe after 3 attempts");
                return resultBuffer;
            }
            continue;
        }

        DWORD bytesRead;
        if (!ReadFile(hPipe, resultBuffer, sizeof(resultBuffer) - 1, &bytesRead, NULL)) {
            CloseHandle(hPipe);
            if (retry == 2) {
                strcpy_s(resultBuffer, "ERROR: Failed to read from pipe after 3 attempts");
                return resultBuffer;
            }
            continue;
        }

        resultBuffer[bytesRead] = '\0';
        CloseHandle(hPipe);
        return resultBuffer;
    }

    strcpy_s(resultBuffer, "ERROR: Unexpected failure in CallFunction");
    return resultBuffer;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        EnsureHelperRunning();
        break;
    case DLL_PROCESS_DETACH:
        if (g_hHelper) {
            HANDLE hShutdownEvent = OpenEventA(EVENT_MODIFY_STATE, FALSE, SHUTDOWN_EVENT_NAME);
            if (hShutdownEvent != NULL) {
                SetEvent(hShutdownEvent);
                CloseHandle(hShutdownEvent);
            }
            WaitForSingleObject(g_hHelper, 5000);
            TerminateProcess(g_hHelper, 0);
            CloseHandle(g_hHelper);
        }
        break;
    }
    return TRUE;
}
  
DLL命令名返回值类型公开备 注
CallFunction文本型 同步,返回函数调用的结果字符串。如果发生错误,返回以 "ERROR:" 开头的错误信息。
DLL库文件名:
Bridge32.dll
在DLL库中对应命令名:
CallFunction
参数名类 型传址数组备 注
dllName文本型表示要调用的 64 位 DLL 的名称
funcName文本型表示要调用的函数名
params文本型表示传递给函数的参数,多个参数用 "|" 分隔

Bridge32.rar

7.56 KB, 下载次数: 44, 下载积分: 精币 -2 枚

售价: 1 枚 精币  [记录]

Helper64.rar

12.86 KB, 下载次数: 45, 下载积分: 精币 -2 枚

售价: 1 枚 精币  [记录]

评分

参与人数 6好评 +4 精币 +6 收起 理由
茉香半糖少冰 + 1 YYDS~!
wa690602724 + 1 感谢分享,很给力!~
光影魔术 + 1 + 1 支持开源~!感谢分享
beatone + 1 支持开源~!感谢分享
人气猫 + 1 + 1 支持开源~!感谢分享
inat + 1 + 2 感谢分享,很给力!~

查看全部评分


本帖被以下淘专辑推荐:

  • · 鱼木|主题: 1573, 订阅: 154
  • · 收藏|主题: 230, 订阅: 6

签到天数: 22 天

发表于 2024-12-17 16:33:32 | 显示全部楼层   四川省成都市
回复 支持 反对

使用道具 举报

结帖率:50% (3/6)

签到天数: 3 天

发表于 2024-12-16 16:48:48 | 显示全部楼层   辽宁省本溪市
Helper64.rar
回复 支持 反对

使用道具 举报

结帖率:50% (3/6)

签到天数: 3 天

发表于 2024-12-16 16:48:17 | 显示全部楼层   辽宁省本溪市
Helper64.rar
回复 支持 反对

使用道具 举报

结帖率:50% (3/6)

签到天数: 3 天

发表于 2024-12-16 16:48:02 | 显示全部楼层   辽宁省本溪市
7.56 KB, 下载次数: 39, 下载积分: 精币 -2 枚
回复 支持 反对

使用道具 举报

结帖率:50% (3/6)

签到天数: 3 天

发表于 2024-12-16 16:47:46 | 显示全部楼层   辽宁省本溪市
7.56 KB, 下载次数: 39, 下载积分: 精币 -2 枚
回复 支持 反对

使用道具 举报

签到天数: 3 天

发表于 2024-12-4 07:08:49 | 显示全部楼层   北京市北京市
感谢分享,很给力!~
回复 支持 反对

使用道具 举报

发表于 2024-10-30 17:59:10 | 显示全部楼层   浙江省丽水市
轻风影 发表于 2024-10-24 19:59
果然是大神,这样也行!

参数三 为结构类型的  怎么传递啊
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)

签到天数: 11 天

发表于 2024-10-30 08:52:05 | 显示全部楼层   广东省汕头市
感谢大神分享~!
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
发表于 2024-10-29 13:14:34 | 显示全部楼层   广西壮族自治区柳州市
感谢分享源码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表