c++ - 卸载注入(inject)的 DLL 时,FreeLibraryAndExitThread 使程序崩溃

标签 c++ windows dll reverse-engineering dll-injection

我正在编写一个 DLL,该 DLL 被注入(inject)到游戏中以便进行一些逆向工程。有一段时间,当我对程序进行更改时,我能够成功地注入(inject)、弹出和重新注入(inject)。我正在使用 FreeLibraryAndExitThread 卸载。

在将 XInput 添加到程序中以便我可以捕获用户输入后,当我调用 FreeLibraryAndExitThread 时,游戏因访问冲突而崩溃。来自 this post ,我猜想当我去卸载时,使用 XInput 会在程序中留下一些“事件”,这就是导致崩溃的原因。老实说,我不知道如何解决这个问题。

这是在退出时导致程序崩溃的代码:

    XINPUT_STATE state;
    ZeroMemory(&state, sizeof(XINPUT_STATE));

    //The problematic line of code
    bool gamepad = XInputGetState(0, &state) == ERROR_SUCCESS; 

    WORD buttonsHeld = state.Gamepad.wButtons;
    WORD buttonsPressed = (~previousButtonState) & state.Gamepad.wButtons;
    WORD buttonsReleased = previousButtonState & (~state.Gamepad.wButtons);

当我删除对 XInputGetState 的调用时,一切正常,我能够在不崩溃的情况下卸载 DLL。

下面是我如何调用程序卸载并退出

    FreeLibraryAndExitThread(hDLL, 0);

hDLLDllMain 的参数 hinstDLL。我还尝试了 GetModuleHandleEx 而不是使用 hinstDLL

我的猜测是:

  • 使用 XInputGetState 使我的程序为 XInput 加载第二个 DLL,或者

  • XInputGetState 在调用时创建对我的 DLL 的某种引用,当我删除我的 DLL 时,它会尝试访问不再存在的内存。

编辑:我做了一些挖掘,问题似乎是添加对 XInputGetState 的调用会导致我的 DLL 加载 XINPUT1_4.dll。我尝试使用 FreeLibrary 卸载它,但它不起作用。

编辑:我进一步缩小了它的范围 - 事实证明,访问冲突是由游戏中的某个线程试图返回到已卸载的 XINPUT1_4.dll 代码的一部分引起的,导致它崩溃。我不知道如何解决这个问题。

最终编辑:这是一个简单的修复,我必须为导致问题的 DLL 调用 LoadLibrary(L"XINPUT1_4.dll")

最佳答案

解决方法如下:

问题是调用 XInputGetState 导致我的 DLL 自动加载 XINPUT1_4.dll,当我调用 FreeLibraryAndExitThread 时,我的 DLL 卸载也强制卸载 XInput DLL .程序中的代码(可能来自 XInput 1.4 中的线程)试图执行不再存在的代码,从而导致访问冲突。

所以解决方案就是在我初始化 DLL 的线程后简单地调用 LoadLibrary(L'XINPUT1_4.dll'),这样当我的 DLL 被卸载时,XInput DLL 会保留在内存中,因为 LoadLibrary 增加引用计数。

(当一个 DLL 的引用计数达到 0 时,它会卸载。当你第一次加载它时它被初始化为 1,LoadLibrary 将它递增 1,调用 FreeLibraryAndExitThread 将它递减 1。所以当一切都说完了,它的引用计数大于 0,并且在卸载我的 DLL 时它保留在内存中)

关于c++ - 卸载注入(inject)的 DLL 时,FreeLibraryAndExitThread 使程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39780590/

相关文章:

C# 漂亮的代码打印库

c++ - Singleton 类中的静态私有(private)数据成员

c++ - std::vector<char> 到 std::vector<T> 转换 c++

c++ - ncbi C++异常(在函数GetSeqEntry()中)

c++ - "#include&lt"和#include之间的区别”

c++ - WASAPI 在 Windows 上捕获的缓冲区大小

c++ - WriteFile 返回错误代码 995

c# - 公开 API 和处理 DLL 的依赖关系并遵守 SOLID 的正确方法是什么?

c++ - 在函数声明中包括数组大小的意义是什么?

java - 为什么我的 Java 项目将 DLL 放在 JAVA_HOME\jre6\bin 中时可以在 Eclipse 中成功调用它们,但使用 java.library.path 却失败?