mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Add option to use global import hook instead of MinHook for OpenProcess (#860)
This commit is contained in:
parent
d1e69ed6fd
commit
c5f84eb27d
13 changed files with 775 additions and 165 deletions
|
|
@ -1,15 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace hooks {
|
||||
class base_untyped_hook {
|
||||
public:
|
||||
virtual ~base_untyped_hook() = default;
|
||||
};
|
||||
|
||||
template<typename>
|
||||
class base_hook;
|
||||
|
||||
template<typename TReturn, typename ... TArgs>
|
||||
class base_hook<TReturn(TArgs...)> {
|
||||
class base_hook<TReturn(TArgs...)> : public base_untyped_hook {
|
||||
using TFn = TReturn(TArgs...);
|
||||
|
||||
private:
|
||||
|
|
@ -22,8 +28,6 @@ namespace hooks {
|
|||
, m_thunk(m_pfnOriginal) {
|
||||
}
|
||||
|
||||
virtual ~base_hook() = default;
|
||||
|
||||
virtual void set_detour(std::function<TFn> fn) {
|
||||
if (!fn)
|
||||
m_thunk.set_target(m_pfnOriginal);
|
||||
|
|
@ -61,7 +65,7 @@ namespace hooks {
|
|||
}
|
||||
|
||||
import_hook(const char* pcszDllName, const char* pcszFunctionName, int hintOrOrdinal)
|
||||
: import_hook(utils::get_imported_function_pointer<TFn>(GetModuleHandleW(nullptr), pcszDllName, pcszFunctionName, hintOrOrdinal)) {
|
||||
: import_hook(utils::loaded_module::current_process().get_imported_function_pointer<TFn>(pcszDllName, pcszFunctionName, hintOrOrdinal)) {
|
||||
}
|
||||
|
||||
~import_hook() override {
|
||||
|
|
@ -119,4 +123,86 @@ namespace hooks {
|
|||
return CallWindowProcW(Base::get_original(), hwnd, msg, wParam, lParam);
|
||||
}
|
||||
};
|
||||
|
||||
class untyped_import_hook : public base_untyped_hook {
|
||||
void** const m_ppfnImportTableItem;
|
||||
void* const m_pfnOriginalImport;
|
||||
|
||||
public:
|
||||
untyped_import_hook(void** ppfnImportTableItem, void* pThunk)
|
||||
: m_pfnOriginalImport(*ppfnImportTableItem)
|
||||
, m_ppfnImportTableItem(ppfnImportTableItem) {
|
||||
|
||||
const utils::memory_tenderizer tenderizer(ppfnImportTableItem, sizeof * ppfnImportTableItem, PAGE_READWRITE);
|
||||
*ppfnImportTableItem = pThunk;
|
||||
}
|
||||
|
||||
~untyped_import_hook() override {
|
||||
MEMORY_BASIC_INFORMATION mbi{};
|
||||
VirtualQuery(m_ppfnImportTableItem, &mbi, sizeof mbi);
|
||||
if (mbi.State != MEM_COMMIT)
|
||||
return;
|
||||
|
||||
const utils::memory_tenderizer tenderizer(m_ppfnImportTableItem, sizeof * m_ppfnImportTableItem, PAGE_READWRITE);
|
||||
*m_ppfnImportTableItem = m_pfnOriginalImport;
|
||||
}
|
||||
};
|
||||
|
||||
class getprocaddress_singleton_import_hook : public std::enable_shared_from_this<getprocaddress_singleton_import_hook> {
|
||||
static inline const char* LogTag = "[global_import_hook]";
|
||||
|
||||
decltype(GetProcAddress)* const m_pfnGetProcAddress;
|
||||
|
||||
utils::thunk<decltype(GetProcAddress)> m_thunk;
|
||||
std::shared_ptr<void> m_getProcAddressHandler;
|
||||
|
||||
void* m_ldrDllNotificationCookie{};
|
||||
std::map<HMODULE, std::string> m_dllNameMap;
|
||||
std::map<HMODULE, std::map<std::string, void*>> m_targetFns;
|
||||
std::map<HMODULE, std::map<std::string, std::map<HMODULE, std::optional<untyped_import_hook>>>> m_hooks;
|
||||
|
||||
public:
|
||||
getprocaddress_singleton_import_hook();
|
||||
~getprocaddress_singleton_import_hook();
|
||||
|
||||
std::shared_ptr<void> set_handler(std::wstring dllName, std::string functionName, void* pfnDetour);
|
||||
|
||||
static std::shared_ptr<getprocaddress_singleton_import_hook> get_instance();
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
FARPROC get_proc_address_handler(HMODULE hModule, LPCSTR lpProcName);
|
||||
|
||||
void hook_module(const utils::loaded_module& mod);
|
||||
};
|
||||
|
||||
template<typename>
|
||||
class global_import_hook;
|
||||
|
||||
template<typename TReturn, typename ... TArgs>
|
||||
class global_import_hook<TReturn(TArgs...)> : public base_untyped_hook {
|
||||
using TFn = TReturn(TArgs...);
|
||||
utils::thunk<TFn> m_thunk;
|
||||
std::shared_ptr<void> m_singleImportHook;
|
||||
|
||||
public:
|
||||
global_import_hook(std::wstring dllName, std::string functionName)
|
||||
: m_thunk(nullptr) {
|
||||
|
||||
m_singleImportHook = getprocaddress_singleton_import_hook::get_instance()->set_handler(dllName, functionName, m_thunk.get_thunk());
|
||||
m_thunk.set_target(reinterpret_cast<TFn*>(m_singleImportHook.get()));
|
||||
}
|
||||
|
||||
virtual void set_detour(std::function<TFn> fn) {
|
||||
if (!fn)
|
||||
m_thunk.set_target(reinterpret_cast<TFn*>(m_singleImportHook.get()));
|
||||
else
|
||||
m_thunk.set_target(std::move(fn));
|
||||
}
|
||||
|
||||
virtual TReturn call_original(TArgs... args) {
|
||||
return reinterpret_cast<TFn*>(m_singleImportHook.get())(std::forward<TArgs>(args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue