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

如何从Web URL将.NET托管DLL注入Unity游戏?

远程内存注入DLL(无本地文件)解决方案

要实现从Web URL直接获取DLL并注入目标进程(跳过本地存储),核心是内存中下载DLL + 手动PE映射——因为系统API LoadLibrary 仅支持从本地文件路径加载,无法直接读取内存中的PE数据。以下是具体实现步骤和关键要点:

1. 内存中下载远程DLL

使用网络库(如WinHTTP、libcurl)直接将URL对应的DLL字节数据读取到本地内存缓冲区,完全避免写入磁盘。以WinHTTP为例,核心流程如下:

LPBYTE DownloadRemoteDLL(const wchar_t* url, SIZE_T* outSize) {
    HINTERNET hSession = WinHttpOpen(L"RemoteInjector", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
    if (!hSession) return nullptr;

    // 示例:拆分GitHub原始链接的主机和路径,实际需做通用URL解析
    HINTERNET hConnect = WinHttpConnect(hSession, L"raw.githubusercontent.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
    if (!hConnect) { WinHttpCloseHandle(hSession); return nullptr; }

    HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/your-repo/path/target.dll", nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
    if (!hRequest) { WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return nullptr; }

    if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) {
        WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession);
        return nullptr;
    }

    if (!WinHttpReceiveResponse(hRequest, nullptr)) {
        WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession);
        return nullptr;
    }

    SIZE_T totalSize = 0;
    LPBYTE buffer = nullptr;
    BYTE tempBuffer[4096];
    DWORD bytesRead;

    while (WinHttpReadData(hRequest, tempBuffer, sizeof(tempBuffer), &bytesRead) && bytesRead > 0) {
        LPBYTE newBuffer = (LPBYTE)realloc(buffer, totalSize + bytesRead);
        if (!newBuffer) { free(buffer); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return nullptr; }
        buffer = newBuffer;
        memcpy(buffer + totalSize, tempBuffer, bytesRead);
        totalSize += bytesRead;
    }

    *outSize = totalSize;
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return buffer;
}

2. 目标进程内存操作

2.1 分配内存

调用 VirtualAllocEx 在目标进程中分配足够容纳DLL数据的内存,初始权限设为 PAGE_READWRITE,后续可调整为执行权限:

LPVOID remoteMem = VirtualAllocEx(hProcess, nullptr, dllSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

2.2 写入DLL数据

用 WriteProcessMemory 将本地内存中的DLL字节写入目标进程的分配内存:

WriteProcessMemory(hProcess, remoteMem, dllBuffer, dllSize, nullptr);

3. 手动PE映射(核心步骤)

由于无法直接调用 LoadLibrary,需要手动实现PE加载逻辑,在目标进程中完成DLL的重定位、导入表解析和入口点调用,核心步骤包括:

  • 解析PE头(IMAGE_DOS_HEADER、IMAGE_NT_HEADERS)
  • 根据节表在目标进程中分配对应内存并复制节数据
  • 处理基址重定位(若DLL编译基址与分配的内存地址不一致)
  • 解析导入表,调用目标进程中的 GetProcAddress 获取依赖函数地址并填充
  • 调用DLL入口点 DllMain

关键坑点

  • 权限不足:注入进程需要目标进程的权限至少包含 PROCESS_CREATE_THREAD、PROCESS_VM_OPERATION、PROCESS_VM_WRITE、PROCESS_VM_READ
  • 位数不兼容:32位注入器无法注入64位进程,反之亦然,必须严格匹配进程位数
  • 重定位表缺失:若DLL编译时指定了固定基址且无重定位表,当目标进程中该基址被占用时会注入失败
  • 网络拦截:确保注入器有网络访问权限,避免被防火墙或安全软件拦截DLL下载请求

简化替代方案

若手动映射过于复杂,可将下载逻辑+手动映射代码编译成一段独立的shellcode,注入到目标进程后执行,由目标进程自行完成DLL的下载和加载,进一步减少本地操作痕迹。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 14:19:55