如何修复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版本与目标系统一致,减少符号差异。
- 将DLL的运行时库设置为静态链接:在VS编译器中,把选项从
- 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
相关产品推荐
相关产品推荐

