-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix deadlock with Windows Loader during execute_while_frozen #51
Conversation
typedef NTSTATUS (WINAPI* PFN_LdrLockLoaderLock)(ULONG Flags, ULONG *State, ULONG_PTR *Cookie); | ||
typedef NTSTATUS (WINAPI* PFN_LdrUnlockLoaderLock)(ULONG Flags, ULONG_PTR Cookie); | ||
|
||
const auto ntdll = GetModuleHandleW(L"ntdll.dll"); | ||
|
||
auto lock_loader = (PFN_LdrLockLoaderLock)GetProcAddress(ntdll, "LdrLockLoaderLock"); | ||
auto unlock_loader = (PFN_LdrUnlockLoaderLock)GetProcAddress(ntdll, "LdrUnlockLoaderLock"); | ||
|
||
if (lock_loader != nullptr && unlock_loader != nullptr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if these were just imported normally. See
safetyhook/src/thread_freezer.cpp
Lines 14 to 19 in 521ae9f
extern "C" { | |
NTSTATUS | |
NTAPI | |
NtGetNextThread(HANDLE ProcessHandle, HANDLE ThreadHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, | |
ULONG Flags, PHANDLE NewThreadHandle); | |
} |
I've started using Another thing I wanted to ask, when I tried to hook d3d present without execute_while_frozen, it crashed inside the hooked present right away because calling original function caused a nullptr exception. Is it not possible to fill that one first, then insert a jump to a hook, eliminating the need of execute_while_frozen? |
Can you explain how you were using |
I was sent a memory dump, and apparently it's not execute_while_frozen issue, I called
Yes, I've replaced a code that utilized minhook with safetyhook, to inject into d3d device vtable calls: static inline bool bind(HMODULE module, std::type_index type_index, uint16_t func_index, void* function, void** original = nullptr)
{
auto target = deviceMethods.at(module).at(type_index).at(func_index);
if (MH_CreateHook(target, function, original) != MH_OK || MH_EnableHook(target) != MH_OK) {
return false;
}
return true;
} static inline void bind(HMODULE module, std::type_index type_index, uint16_t func_index, void* function, SafetyHookInline& hook)
{
auto target = deviceMethods.at(module).at(type_index).at(func_index);
try
{
safetyhook::execute_while_frozen([&]
{
hook = safetyhook::create_inline(target, function);
});
}
catch (const std::exception& e) {}
} It doesn't work without execute_while_frozen, crashes. Links to code mentioned above: |
I'm confused by this code. You shouldn't ever have to wrap |
Unless you absolutely know you have to use it, then you shouldn't use it. @ThirteenAG I guess we're more curious to why exactly you need to use it here. Could you elaborate on this or provide more details? Are you sure you need to use |
Yes, but it didn't work for me with Max Payne 3 d3d hooking and resulted in a crash. It doesn't happen with execute_while_frozen.
Crash on this line: https://github.com/ThirteenAG/FusionDxHook/blob/main/includes/fusiondxhook.h#L640 That's literally all I have to do to trigger the crash immediately (commented lines): static inline void bind(HMODULE module, std::type_index type_index, uint16_t func_index, void* function, SafetyHookInline& hook)
{
auto target = deviceMethods.at(module).at(type_index).at(func_index);
try
{
//safetyhook::execute_while_frozen([&]
//{
hook = safetyhook::create_inline(target, function);
//});
}
catch (const std::exception& e) {}
} As I've said, works inside execute_while_frozen, no problems. I'd assume due to create_inline hooking, but |
@ThirteenAG can you try this quick test PR I threw together? #63 You'll need to remove |
Tested GTAIV/Max Payne 3 plugins, and dx hook tests with all uses of execute_while_frozen removed, works fine. |
Thanks for the extra information, it really helps. And thanks for testing it. I think this change is better in the long term since it's technically more portable too. |
Closing this since I landed thread trapping. |
I noticed a freeze when calling safetyhook::create_inline, and I assume this is where the problem came from. Either that or it was one of my many calls to execute_while_frozen.