FreeLibraryAndExitThread crashes program when unlo

2019-05-23 07:26发布

I am writing a DLL that gets injected into a game in order to play around with some reverse engineering. 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.

After adding XInput to the program so I could catch user input, the game crashes with an access violation when I call 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. 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.

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. I've also tried GetModuleHandleEx instead of using hinstDLL.

My guess is either:

  • Using XInputGetState makes my program load a second DLL for XInput, or

  • 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.

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. I tried using FreeLibrary to unload it but that isn't working.

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. 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.

1条回答
欢心
2楼-- · 2019-05-23 08:16

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. 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.

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.

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

查看更多
登录 后发表回答