简体   繁体   English

卸载注入的 DLL 时,FreeLibraryAndExitThread 使程序崩溃

[英]FreeLibraryAndExitThread crashes program when unloading injected DLL

I am writing a DLL that gets injected into a game in order to play around with some reverse engineering.我正在编写一个注入游戏的 DLL,以便进行一些逆向工程。 For a while I was able to successfully inject, eject and reinject as I made changes to the program.有一段时间,当我对程序进行更改时,我能够成功地注入、弹出和重新注入。 I'm using FreeLibraryAndExitThread to unload.我正在使用FreeLibraryAndExitThread卸载。

After adding XInput to the program so I could catch user input, the game crashes with an access violation when I call FreeLibraryAndExitThread .在将 XInput 添加到程序中以便我可以捕获用户输入后,当我调用FreeLibraryAndExitThread时,游戏因访问冲突而崩溃。 Going from this post , I'm guessing that using XInput is leaving something 'live' in the program when I go to unload, and that's what's causing the crash.这篇文章开始,我猜测使用 XInput 会在我卸载时在程序中留下一些“活动”的东西,这就是导致崩溃的原因。 I'm honestly at a loss as to how to fix this.老实说,我不知道如何解决这个问题。

Here's the code that's crashing the program on exit:这是在退出时使程序崩溃的代码:

    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);

When I remove the call to XInputGetState , everything works just fine and I'm able to unload the DLL without crashing.当我删除对XInputGetState的调用时,一切正常,我能够卸载 DLL 而不会崩溃。

And here's how I'm calling for the program to unload and exit这就是我如何调用程序卸载和退出

    FreeLibraryAndExitThread(hDLL, 0);

Where hDLL is the argument hinstDLL from DllMain .hDLL是参数hinstDLLDllMain I've also tried GetModuleHandleEx instead of using hinstDLL .我也试过GetModuleHandleEx而不是使用hinstDLL

My guess is either:我的猜测是:

  • Using XInputGetState makes my program load a second DLL for XInput , or使用XInputGetState使我的程序为XInput加载第二个DLL,或者

  • XInputGetState is creating some sort of reference to my DLL when called and when I remove my DLL, it's trying to access memory that's no longer there. XInputGetState在调用时创建了对我的 DLL 的某种引用,当我删除我的 DLL 时,它试图访问不再存在的内存。

EDIT: I did a bit of digging and the problem seems to be that adding the call to XInputGetState causes my DLL to load XINPUT1_4.dll .编辑:我做了一些挖掘,问题似乎是添加对XInputGetState的调用会导致我的 DLL 加载XINPUT1_4.dll I tried using FreeLibrary to unload it but that isn't working.我尝试使用FreeLibrary卸载它,但这不起作用。

EDIT: I narrowed it down some more - it turns out that the access violation is being caused by some thread within the game trying to return to part of XINPUT1_4.dll's code, which is unloaded, making it crash.编辑:我进一步缩小了范围 - 结果表明访问冲突是由游戏中的某个线程试图返回 XINPUT1_4.dll 代码的一部分引起的,该代码已卸载,导致崩溃。 And I have no clue how to fix that.我不知道如何解决这个问题。

Final Edit: It was a simple fix, I had to call LoadLibrary(L"XINPUT1_4.dll") for the DLL that was causing the issue.最终编辑:这是一个简单的修复,我不得不为导致问题的 DLL 调用LoadLibrary(L"XINPUT1_4.dll")

Here's the solution:这是解决方案:

The problem was that invoking XInputGetState caused my DLL to automatically load XINPUT1_4.dll , and when I called FreeLibraryAndExitThread, my DLL unloading forced the XInput DLL to unload as well.问题是调用XInputGetState导致我的 DLL 自动加载XINPUT1_4.dll ,并且当我调用 FreeLibraryAndExitThread 时,我的 DLL 卸载也强制 XInput DLL 卸载。 Code within the program (probably from a thread in XInput 1.4) attempted to execute code that was no longer there, causing an access violation.程序中的代码(可能来自 XInput 1.4 中的线程)试图执行不再存在的代码,从而导致访问冲突。

So the solution was simply to call LoadLibrary(L'XINPUT1_4.dll') after I initialize my DLL's thread so that when my DLL is unloaded, the XInput DLL stays in memory because the LoadLibrary increases the reference count.所以解决方案只是在我初始化我的 DLL 的线程后调用LoadLibrary(L'XINPUT1_4.dll') ,这样当我的 DLL 被卸载时,XInput DLL 保留在内存中,因为LoadLibrary增加了引用计数。

(When a DLL's reference count reaches 0, it unloads. It is initialized as 1 when you first load it, LoadLibrary increments it by 1, and calling FreeLibraryAndExitThread decrements it by 1. So when all is said and done, its reference count is above 0 and it remains in memory as my DLL is unloaded) (当 DLL 的引用计数达到 0 时,它会卸载。第一次加载时它被初始化为 1,LoadLibrary 将它加 1,调用 FreeLibraryAndExitThread 将它减 1。所以当一切都说完了,它的引用计数高于0 并且它在我的 DLL 被卸载时保留在内存中)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM