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

如何修复Cheat Engine注入.NET应用时的msvcrt!_dllonexit DLL注入错误

问题描述

尝试用Cheat Engine将C/C++编写的DLL注入.NET应用时,出现以下错误:

dllInject failed: Failed injecting the DLL Force load module failed: failed finding address of msvcrt!_dllonexit

本人对.NET编程不熟悉,不确定是否必须改用.NET编写DLL才能正常注入。曾尝试先注入msvcrt.dll,但问题未解决,依然收到上述错误,预期DLL能成功注入且无报错。

注入用C/C++ DLL代码

#include <windows.h>
#include <stdio.h>

// Function pointer for managed code function
typedef void(__stdcall *ActivateClickFunction)();

// Function prototype
void InjectedMain();

// Entry point of DLL
BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        // Load msvcrt.dll explicitly
        {
            HMODULE hMsvcrt = LoadLibraryA("msvcrt.dll");
            if (hMsvcrt == NULL)
            {
                MessageBoxW(NULL, L"Failed to load msvcrt.dll!", L"Error", MB_OK | MB_ICONERROR);
                return FALSE; // Or handle the error as appropriate
            }
        }

        // Injected into process
        MessageBoxW(NULL, L"SRhij.dll loaded successfully!", L"DLL Injector", MB_OK | MB_ICONINFORMATION);
        InjectedMain();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

// Function to find MainWindow and invoke Activate_Click method
void InjectedMain()
{
    // Find the target window by class name or other criteria
    HWND mainWindowHandle = FindWindowW(L"iRemovalProWPF.MainWindow", NULL);

    if (mainWindowHandle == NULL)
    {
        MessageBoxW(NULL, L"Failed to find MainWindow!", L"Error", MB_OK | MB_ICONERROR);
        return;
    }

    // Get process ID of the window
    DWORD processId;
    GetWindowThreadProcessId(mainWindowHandle, &processId);

    // Open process with necessary permissions
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
    if (hProcess == NULL)
    {
        MessageBoxW(NULL, L"Failed to open process!", L"Error", MB_OK | MB_ICONERROR);
        return;
    }

    // Specify the path of mscoree.dll
    LPCWSTR dllPath = L"mscoree.dll";

    // Load .NET runtime into the target process using full path
    HMODULE hDotNetModule = LoadLibraryExW(dllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
    if (hDotNetModule == NULL)
    {
        DWORD error = GetLastError();
        WCHAR errorMsg[256];
        // Use snwprintf for buffer safety
        _snwprintf(errorMsg, 256, L"Failed to load %s! Error code: %lu", dllPath, error);
        errorMsg[255] = L'\0'; // Ensure null termination
        MessageBoxW(NULL, errorMsg, L"Error", MB_OK | MB_ICONERROR);
        CloseHandle(hProcess);  // Assuming hProcess is a valid handle to the target process
        return;
    }

    // Get the address of the managed entry point method in the target process
    ActivateClickFunction activateClick = (ActivateClickFunction) GetProcAddress(hDotNetModule, "Someting_That_is+under_those_program"); // that is example 
    if (activateClick == NULL)
    {
        DWORD error = GetLastError();
        WCHAR errorMsg[256];
        // Use snwprintf for buffer safety
        _snwprintf(errorMsg, 256, L"Failed to get address of Activate_Click method! Error code: %lu", error);
        errorMsg[255] = L'\0'; // Ensure null termination
        MessageBoxW(NULL, errorMsg, L"Error", MB_OK | MB_ICONERROR);
        FreeLibrary(hDotNetModule);
        CloseHandle(hProcess);
        return;
    }

    // Call the managed method in the target process
    activateClick();

    // Cleanup
    FreeLibrary(hDotNetModule);
    CloseHandle(hProcess);
}
问题分析与解决建议
  • 错误本质:该错误并非目标进程缺少msvcrt.dll,而是Cheat Engine注入器在加载你的DLL时,无法匹配到目标进程中msvcrt.dll的_dllonexit符号。核心原因是你的DLL编译时依赖的C运行时库版本,与目标.NET进程加载的msvcrt版本不兼容。
  • 无需切换到.NET DLL:C/C++ DLL完全可以注入.NET进程,不需要改用.NET编写DLL。
  • 编译选项调整:
    • 将DLL的运行时库设置为静态链接:在VS编译器中,把选项从/MD(动态多线程)或/MDd(动态多线程调试)改为/MT(静态多线程)或/MTd(静态多线程调试)。静态链接会把C运行时库打包进你的DLL,彻底避免对目标进程msvcrt版本的依赖。
    • 确保编译使用的Windows SDK版本与目标系统一致,减少符号差异。
  • DllMain轻量化改造:
    • 不要在DllMain中执行加载DLL、弹窗、复杂逻辑等操作,注入时进程处于临界状态,这类操作容易触发加载失败。应把InjectedMain放到新线程中执行:
      case DLL_PROCESS_ATTACH:
          // 移除原有的加载msvcrt和弹窗代码,改为创建线程
          CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)InjectedMain, NULL, 0, NULL);
          break;
      
  • 修正.NET方法调用逻辑:你的代码中试图通过GetProcAddress从mscoree.dll获取托管方法地址的方式完全错误。.NET托管方法不会直接导出到mscoree.dll,要调用目标进程的托管方法,需使用.NET宿主API(如CLRCreateInstance、ICLRRuntimeHost)加载目标程序集并反射调用方法,或使用EasyHook等第三方库简化操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:04:59