update
This commit is contained in:
parent
7ee55162d8
commit
2f757c7f28
@ -12,6 +12,10 @@ namespace arxan
|
||||
utils::hook::detour nt_close_hook;
|
||||
utils::hook::detour nt_query_information_process_hook;
|
||||
|
||||
#define ProcessDebugPort 7
|
||||
#define ProcessDebugObjectHandle 30 // WinXP source says 31?
|
||||
#define ProcessDebugFlags 31 // WinXP source says 32?
|
||||
|
||||
NTSTATUS WINAPI nt_query_information_process_stub(const HANDLE handle, const PROCESSINFOCLASS info_class,
|
||||
const PVOID info,
|
||||
const ULONG info_length, const PULONG ret_length)
|
||||
@ -31,24 +35,23 @@ namespace arxan
|
||||
GetWindowThreadProcessId(shell_window, &explorer_pid);
|
||||
}
|
||||
|
||||
// InheritedFromUniqueProcessId
|
||||
static_cast<PPROCESS_BASIC_INFORMATION>(info)->Reserved3 = PVOID(DWORD64(explorer_pid));
|
||||
}
|
||||
else if (info_class == 30) // ProcessDebugObjectHandle
|
||||
else if (info_class == ProcessDebugObjectHandle)
|
||||
{
|
||||
*static_cast<HANDLE*>(info) = nullptr;
|
||||
|
||||
return 0xC0000353;
|
||||
}
|
||||
else if (info_class == 7) // ProcessDebugPort
|
||||
else if (info_class == ProcessDebugPort)
|
||||
{
|
||||
*static_cast<HANDLE*>(info) = nullptr;
|
||||
}
|
||||
else if (info_class == 31)
|
||||
else if (info_class == ProcessDebugFlags)
|
||||
{
|
||||
*static_cast<ULONG*>(info) = 1;
|
||||
}
|
||||
|
||||
//https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -73,6 +76,11 @@ namespace arxan
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
if (info->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION)
|
||||
{
|
||||
//MessageBoxA(0, 0, "AV", 0);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
@ -82,86 +90,31 @@ namespace arxan
|
||||
peb->BeingDebugged = false;
|
||||
*reinterpret_cast<PDWORD>(LPSTR(peb) + 0xBC) &= ~0x70;
|
||||
}
|
||||
|
||||
void remove_hardware_breakpoints()
|
||||
{
|
||||
CONTEXT context;
|
||||
ZeroMemory(&context, sizeof(context));
|
||||
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
|
||||
auto* const thread = GetCurrentThread();
|
||||
GetThreadContext(thread, &context);
|
||||
|
||||
context.Dr0 = 0;
|
||||
context.Dr1 = 0;
|
||||
context.Dr2 = 0;
|
||||
context.Dr3 = 0;
|
||||
context.Dr6 = 0;
|
||||
context.Dr7 = 0;
|
||||
|
||||
SetThreadContext(thread, &context);
|
||||
}
|
||||
|
||||
BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context)
|
||||
{
|
||||
return SetThreadContext(thread, context);
|
||||
}
|
||||
|
||||
utils::hook::detour doexit_hook;
|
||||
void doexit_stub()
|
||||
{
|
||||
MessageBoxA(0, "doexit", "", 0);
|
||||
return doexit_hook.invoke<void>();
|
||||
}
|
||||
|
||||
utils::hook::detour integrity_check1_hook;
|
||||
__int64 integrity_check1_stub_hook(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5)
|
||||
{
|
||||
__int64 result;
|
||||
doexit_hook.disable();
|
||||
integrity_check1_hook.disable();
|
||||
|
||||
printf("[ arxan ]: integrity check 1 bypassing...\n");
|
||||
result = integrity_check1_hook.invoke<__int64>(a1, a2, a3, a4, a5);
|
||||
printf("[ arxan ]: integrity check 1 passed!\n");
|
||||
|
||||
doexit_hook.enable();
|
||||
integrity_check1_hook.enable();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void* load_import(const std::string& library, const std::string& function) override
|
||||
{
|
||||
if (function == "SetThreadContext")
|
||||
{
|
||||
//return set_thread_context_stub;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void post_load() override
|
||||
{
|
||||
hide_being_debugged();
|
||||
scheduler::loop(hide_being_debugged, scheduler::pipeline::async);
|
||||
|
||||
const utils::nt::library ntdll("ntdll.dll");
|
||||
|
||||
nt_close_hook.create(ntdll.get_proc<void*>("NtClose"), nt_close_stub);
|
||||
nt_query_information_process_hook.create(ntdll.get_proc<void*>("NtQueryInformationProcess"),
|
||||
nt_query_information_process_stub);
|
||||
// https://www.geoffchappell.com/studies/windows/win32/ntdll/api/index.htm
|
||||
|
||||
const auto nt_query_information_process = ntdll.get_proc<void*>("NtQueryInformationProcess");
|
||||
nt_query_information_process_hook.create(nt_query_information_process,
|
||||
nt_query_information_process_stub);
|
||||
nt_query_information_process_hook.move();
|
||||
|
||||
AddVectoredExceptionHandler(1, exception_filter);
|
||||
}
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
doexit_hook.create(0x12D7348_b, doexit_stub);
|
||||
|
||||
integrity_check1_hook.create(0xC6D8B0_b, integrity_check1_stub_hook); // SV_SpawnServer
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -6,12 +6,8 @@
|
||||
#include "version.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
//#include "dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
// Fonts are used in game:
|
||||
// Fonts used in game:
|
||||
// fonts/blender_pro_bold.ttf, fonts/blender_pro_book.ttf, fonts/blender_pro_heavy.ttf, fonts/blender_pro_medium.ttf
|
||||
// fonts/changelingneo-regular.ttf, fonts/dev.ttf, fonts/fira_mono_bold.ttf, fonts/fira_mono_regular.ttf, fonts/iw6_digital.ttf
|
||||
|
||||
@ -19,15 +15,9 @@ namespace branding
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour ui_get_formatted_build_number_hook;
|
||||
|
||||
float color[4] = { 0.666f, 0.666f, 0.666f, 0.666f };
|
||||
|
||||
const char* ui_get_formatted_build_number_stub()
|
||||
{
|
||||
const auto* const build_num = ui_get_formatted_build_number_hook.invoke<const char*>();
|
||||
return utils::string::va("%s (%s)", VERSION, build_num);
|
||||
}
|
||||
game::dvar_t* branding;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -35,20 +25,23 @@ namespace branding
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
localized_strings::override("LUA_MENU_LEGAL_COPYRIGHT", "IW7-MOD");
|
||||
|
||||
localized_strings::override("LUA_MENU_MULTIPLAYER_CAPS", "IW7-MOD: MULTIPLAYER");
|
||||
localized_strings::override("LUA_MENU_ALIENS_CAPS", "IW7-MOD: ZOMBIES");
|
||||
|
||||
//dvars::override::set_string("version", utils::string::va("IW7-Mod %s", VERSION));
|
||||
|
||||
//ui_get_formatted_build_number_hook.create(0x1DF300_b, ui_get_formatted_build_number_stub); can't find
|
||||
branding = game::Dvar_RegisterBool("branding", true, game::DvarFlags::DVAR_FLAG_SAVED, "Show branding in the top right corner");
|
||||
|
||||
scheduler::loop([]()
|
||||
{
|
||||
const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20);
|
||||
if (font)
|
||||
if (branding && branding->current.enabled)
|
||||
{
|
||||
game::R_AddCmdDrawText("IW7-Mod: " VERSION, 0x7FFFFFFF, font, 10.f,
|
||||
5.f + static_cast<float>(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0);
|
||||
const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20);
|
||||
if (font)
|
||||
{
|
||||
game::R_AddCmdDrawText("IW7-Mod: " VERSION, 0x7FFFFFFF, font, 10.f,
|
||||
5.f + static_cast<float>(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0);
|
||||
}
|
||||
}
|
||||
}, scheduler::pipeline::renderer);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ namespace console
|
||||
DWORD WINAPI console(LPVOID)
|
||||
{
|
||||
ShowWindow(GetConsoleWindow(), SW_SHOW);
|
||||
SetConsoleTitle("IW7-Mod");
|
||||
SetConsoleTitleA("IW7-Mod Console");
|
||||
|
||||
std::string cmd;
|
||||
exit = false;
|
||||
@ -416,6 +416,14 @@ namespace console
|
||||
//setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
~component() override
|
||||
{
|
||||
if (!console::is_enabled() || native::is_enabled()) return;
|
||||
|
||||
if (sys::icon) DestroyIcon(sys::icon);
|
||||
if (sys::logo) DeleteObject(sys::logo);
|
||||
}
|
||||
|
||||
void post_start() override
|
||||
{
|
||||
if (console::is_enabled())
|
||||
|
@ -11,25 +11,16 @@ namespace logger
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void nullsub_6_stub(const char* msg, ...)
|
||||
void sys_print_stub(const char* msg)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
console::info("%s", buffer);
|
||||
}
|
||||
console::info(msg);
|
||||
}
|
||||
|
||||
void nullsub_6()
|
||||
void sys_print_stubs()
|
||||
{
|
||||
utils::hook::call(0xC6E57A_b, nullsub_6_stub);
|
||||
utils::hook::call(0xC6E57A_b, sys_print_stub); // SV_SpawnServer: completed\n
|
||||
utils::hook::call(0xC13641_b, sys_print_stub); // SV_CmdsSP_MapRestart: completed\n
|
||||
utils::hook::jump(0x519772_b, sys_print_stub); // OnlineAutoTest:: Map load success. Server is listen.\n
|
||||
}
|
||||
|
||||
void R_WarnOncePerFrame_print_stub(char* buffer, size_t buffer_length, char* msg, va_list va)
|
||||
@ -44,14 +35,14 @@ namespace logger
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
//nullsub_6();
|
||||
sys_print_stubs();
|
||||
|
||||
if (!game::environment::is_dedi())
|
||||
{
|
||||
//utils::hook::call(0xE4B121_b, R_WarnOncePerFrame_print_stub);
|
||||
utils::hook::call(0xE4B121_b, R_WarnOncePerFrame_print_stub);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(logger::component)
|
||||
//REGISTER_COMPONENT(logger::component)
|
@ -3,9 +3,6 @@
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
//#include "dvars.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
|
@ -7,13 +7,12 @@ namespace resources
|
||||
namespace
|
||||
{
|
||||
HICON icon;
|
||||
HANDLE splash, logo;
|
||||
HANDLE splash;
|
||||
|
||||
HANDLE WINAPI load_image_a(const HINSTANCE handle, LPCSTR name, const UINT type, const int c_x, const int c_y,
|
||||
const UINT load)
|
||||
{
|
||||
const utils::nt::library self;
|
||||
if (!IS_INTRESOURCE(name) && name == "logo.bmp"s) return logo;
|
||||
if (self.get_handle() == handle && name == LPCSTR(0x64)) return splash;
|
||||
|
||||
return LoadImageA(handle, name, type, c_x, c_y, load);
|
||||
@ -22,7 +21,7 @@ namespace resources
|
||||
HICON WINAPI load_icon_a(const HINSTANCE handle, const LPCSTR name)
|
||||
{
|
||||
const utils::nt::library self;
|
||||
if (self.get_handle() == handle && name == LPCSTR(2)) return icon;
|
||||
if (self.get_handle() == handle && name == LPCSTR(1)) return icon;
|
||||
|
||||
return LoadIconA(handle, name);
|
||||
}
|
||||
@ -34,7 +33,6 @@ namespace resources
|
||||
~component() override
|
||||
{
|
||||
if (icon) DestroyIcon(icon);
|
||||
if (logo) DeleteObject(logo);
|
||||
if (splash) DeleteObject(splash);
|
||||
}
|
||||
|
||||
@ -43,7 +41,6 @@ namespace resources
|
||||
const utils::nt::library self;
|
||||
|
||||
icon = LoadIconA(self.get_handle(), MAKEINTRESOURCEA(ID_ICON));
|
||||
logo = LoadImageA(self.get_handle(), MAKEINTRESOURCEA(IMAGE_LOGO), 0, 0, 0, LR_COPYFROMRESOURCE);
|
||||
splash = LoadImageA(self.get_handle(), MAKEINTRESOURCEA(IMAGE_SPLASH), 0, 0, 0, LR_COPYFROMRESOURCE);
|
||||
}
|
||||
|
||||
|
@ -185,4 +185,4 @@ namespace steam_proxy
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(steam_proxy::component)
|
||||
//REGISTER_COMPONENT(steam_proxy::component)
|
||||
|
@ -90,11 +90,11 @@ namespace system_check
|
||||
if (!is_valid())
|
||||
{
|
||||
MessageBoxA(nullptr, "Your game files are outdated or unsupported.\n"
|
||||
"Please get the latest officially supported Call of Duty: Modern Warfare Remastered files, or you will get random crashes and issues.",
|
||||
"Please get the latest officially supported Call of Duty: Infinite Warfare files, or you will get random crashes and issues.",
|
||||
"Invalid game files!", MB_ICONINFORMATION);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(system_check::component)
|
||||
//REGISTER_COMPONENT(system_check::component)
|
||||
|
@ -7,22 +7,26 @@ namespace utils::hook
|
||||
{
|
||||
namespace
|
||||
{
|
||||
[[maybe_unused]] class _
|
||||
void* initialize_min_hook()
|
||||
{
|
||||
public:
|
||||
_()
|
||||
static class min_hook_init
|
||||
{
|
||||
if (MH_Initialize() != MH_OK)
|
||||
public:
|
||||
min_hook_init()
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize MinHook");
|
||||
if (MH_Initialize() != MH_OK)
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize MinHook");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~_()
|
||||
{
|
||||
MH_Uninitialize();
|
||||
}
|
||||
} __;
|
||||
~min_hook_init()
|
||||
{
|
||||
MH_Uninitialize();
|
||||
}
|
||||
} min_hook_init;
|
||||
return &min_hook_init;
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::pushad64()
|
||||
@ -95,11 +99,18 @@ namespace utils::hook
|
||||
return Assembler::jmp(size_t(target));
|
||||
}
|
||||
|
||||
detour::detour(const size_t place, void* target) : detour(reinterpret_cast<void*>(place), target)
|
||||
detour::detour()
|
||||
{
|
||||
(void)initialize_min_hook();
|
||||
}
|
||||
|
||||
detour::detour(const size_t place, void* target)
|
||||
: detour(reinterpret_cast<void*>(place), target)
|
||||
{
|
||||
}
|
||||
|
||||
detour::detour(void* place, void* target)
|
||||
: detour()
|
||||
{
|
||||
this->create(place, target);
|
||||
}
|
||||
@ -109,13 +120,19 @@ namespace utils::hook
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void detour::enable() const
|
||||
void detour::enable()
|
||||
{
|
||||
MH_EnableHook(this->place_);
|
||||
|
||||
if (!this->moved_data_.empty())
|
||||
{
|
||||
this->move();
|
||||
}
|
||||
}
|
||||
|
||||
void detour::disable() const
|
||||
void detour::disable()
|
||||
{
|
||||
this->un_move();
|
||||
MH_DisableHook(this->place_);
|
||||
}
|
||||
|
||||
@ -141,11 +158,18 @@ namespace utils::hook
|
||||
{
|
||||
if (this->place_)
|
||||
{
|
||||
this->un_move();
|
||||
MH_RemoveHook(this->place_);
|
||||
}
|
||||
|
||||
this->place_ = nullptr;
|
||||
this->original_ = nullptr;
|
||||
this->moved_data_ = {};
|
||||
}
|
||||
|
||||
void detour::move()
|
||||
{
|
||||
this->moved_data_ = move_hook(this->place_);
|
||||
}
|
||||
|
||||
void* detour::get_original() const
|
||||
@ -153,6 +177,14 @@ namespace utils::hook
|
||||
return this->original_;
|
||||
}
|
||||
|
||||
void detour::un_move()
|
||||
{
|
||||
if (!this->moved_data_.empty())
|
||||
{
|
||||
copy(this->place_, this->moved_data_.data(), this->moved_data_.size());
|
||||
}
|
||||
}
|
||||
|
||||
bool iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub)
|
||||
{
|
||||
if (!library.is_valid()) return false;
|
||||
@ -230,12 +262,16 @@ namespace utils::hook
|
||||
return call(pointer, reinterpret_cast<void*>(data));
|
||||
}
|
||||
|
||||
void jump(void* pointer, void* data, const bool use_far)
|
||||
void jump(void* pointer, void* data, const bool use_far, const bool use_safe)
|
||||
{
|
||||
static const unsigned char jump_data[] = {
|
||||
0x48, 0xb8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xff, 0xe0
|
||||
};
|
||||
|
||||
static const unsigned char jump_data_safe[] = {
|
||||
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
if (!use_far && is_relatively_far(pointer, data))
|
||||
{
|
||||
throw std::runtime_error("Too far away to create 32bit relative branch");
|
||||
@ -245,8 +281,16 @@ namespace utils::hook
|
||||
|
||||
if (use_far)
|
||||
{
|
||||
copy(patch_pointer, jump_data, sizeof(jump_data));
|
||||
copy(patch_pointer + 2, &data, sizeof(data));
|
||||
if (use_safe)
|
||||
{
|
||||
copy(patch_pointer, jump_data_safe, sizeof(jump_data_safe));
|
||||
copy(patch_pointer + sizeof(jump_data_safe), &data, sizeof(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
copy(patch_pointer, jump_data, sizeof(jump_data));
|
||||
copy(patch_pointer + 2, &data, sizeof(data));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -255,14 +299,14 @@ namespace utils::hook
|
||||
}
|
||||
}
|
||||
|
||||
void jump(const size_t pointer, void* data, const bool use_far)
|
||||
void jump(const size_t pointer, void* data, const bool use_far, const bool use_safe)
|
||||
{
|
||||
return jump(reinterpret_cast<void*>(pointer), data, use_far);
|
||||
return jump(reinterpret_cast<void*>(pointer), data, use_far, use_safe);
|
||||
}
|
||||
|
||||
void jump(const size_t pointer, const size_t data, const bool use_far)
|
||||
void jump(const size_t pointer, const size_t data, const bool use_far, const bool use_safe)
|
||||
{
|
||||
return jump(pointer, reinterpret_cast<void*>(data), use_far);
|
||||
return jump(pointer, reinterpret_cast<void*>(data), use_far, use_safe);
|
||||
}
|
||||
|
||||
void* assemble(const std::function<void(assembler&)>& asm_function)
|
||||
@ -297,6 +341,41 @@ namespace utils::hook
|
||||
return inject(reinterpret_cast<void*>(pointer), data);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> move_hook(void* pointer)
|
||||
{
|
||||
std::vector<uint8_t> original_data{};
|
||||
|
||||
auto* data_ptr = static_cast<uint8_t*>(pointer);
|
||||
if (data_ptr[0] == 0xE9)
|
||||
{
|
||||
original_data.resize(6);
|
||||
memmove(original_data.data(), pointer, original_data.size());
|
||||
|
||||
auto* target = follow_branch(data_ptr);
|
||||
nop(data_ptr, 1);
|
||||
jump(data_ptr + 1, target);
|
||||
}
|
||||
else if (data_ptr[0] == 0xFF && data_ptr[1] == 0x25)
|
||||
{
|
||||
original_data.resize(15);
|
||||
memmove(original_data.data(), pointer, original_data.size());
|
||||
|
||||
copy(data_ptr + 1, data_ptr, 14);
|
||||
nop(data_ptr, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("No branch instruction found");
|
||||
}
|
||||
|
||||
return original_data;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> move_hook(const size_t pointer)
|
||||
{
|
||||
return move_hook(reinterpret_cast<void*>(pointer));
|
||||
}
|
||||
|
||||
void* follow_branch(void* address)
|
||||
{
|
||||
auto* const data = static_cast<uint8_t*>(address);
|
||||
@ -307,4 +386,4 @@ namespace utils::hook
|
||||
|
||||
return extract<void*>(data + 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,21 +10,21 @@ namespace utils::hook
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<size_t entries>
|
||||
template <size_t Entries>
|
||||
std::vector<size_t(*)()> get_iota_functions()
|
||||
{
|
||||
if constexpr (entries == 0)
|
||||
if constexpr (Entries == 0)
|
||||
{
|
||||
std::vector<size_t(*)()> functions;
|
||||
return functions;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto functions = get_iota_functions<entries - 1>();
|
||||
auto functions = get_iota_functions<Entries - 1>();
|
||||
functions.emplace_back([]()
|
||||
{
|
||||
return entries - 1;
|
||||
});
|
||||
{
|
||||
return Entries - 1;
|
||||
});
|
||||
return functions;
|
||||
}
|
||||
}
|
||||
@ -36,8 +36,8 @@ namespace utils::hook
|
||||
// Example:
|
||||
// ID3D11Device* device = ...
|
||||
// auto entry = get_vtable_entry(device, &ID3D11Device::CreateTexture2D);
|
||||
template <size_t entries = 100, typename Class, typename T, typename... Args>
|
||||
void** get_vtable_entry(Class* obj, T (Class::* entry)(Args ...))
|
||||
template <size_t Entries = 100, typename Class, typename T, typename... Args>
|
||||
void** get_vtable_entry(Class* obj, T(Class::* entry)(Args ...))
|
||||
{
|
||||
union
|
||||
{
|
||||
@ -47,11 +47,11 @@ namespace utils::hook
|
||||
|
||||
func = entry;
|
||||
|
||||
auto iota_functions = detail::get_iota_functions<entries>();
|
||||
auto iota_functions = detail::get_iota_functions<Entries>();
|
||||
auto* object = iota_functions.data();
|
||||
|
||||
using FakeFunc = size_t(__thiscall*)(void* self);
|
||||
auto index = static_cast<FakeFunc>(pointer)(&object);
|
||||
using fake_func = size_t(__thiscall*)(void* self);
|
||||
auto index = static_cast<fake_func>(pointer)(&object);
|
||||
|
||||
void** obj_v_table = *reinterpret_cast<void***>(obj);
|
||||
return &obj_v_table[index];
|
||||
@ -85,7 +85,7 @@ namespace utils::hook
|
||||
class detour
|
||||
{
|
||||
public:
|
||||
detour() = default;
|
||||
detour();
|
||||
detour(void* place, void* target);
|
||||
detour(size_t place, void* target);
|
||||
~detour();
|
||||
@ -99,13 +99,15 @@ namespace utils::hook
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->~detour();
|
||||
this->clear();
|
||||
|
||||
this->place_ = other.place_;
|
||||
this->original_ = other.original_;
|
||||
this->moved_data_ = other.moved_data_;
|
||||
|
||||
other.place_ = nullptr;
|
||||
other.original_ = nullptr;
|
||||
other.moved_data_ = {};
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -114,13 +116,15 @@ namespace utils::hook
|
||||
detour(const detour&) = delete;
|
||||
detour& operator=(const detour&) = delete;
|
||||
|
||||
void enable() const;
|
||||
void disable() const;
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
void create(void* place, void* target);
|
||||
void create(size_t place, void* target);
|
||||
void clear();
|
||||
|
||||
void move();
|
||||
|
||||
template <typename T>
|
||||
T* get() const
|
||||
{
|
||||
@ -136,8 +140,11 @@ namespace utils::hook
|
||||
[[nodiscard]] void* get_original() const;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> moved_data_{};
|
||||
void* place_{};
|
||||
void* original_{};
|
||||
|
||||
void un_move();
|
||||
};
|
||||
|
||||
bool iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub);
|
||||
@ -154,15 +161,18 @@ namespace utils::hook
|
||||
void call(size_t pointer, void* data);
|
||||
void call(size_t pointer, size_t data);
|
||||
|
||||
void jump(void* pointer, void* data, bool use_far = false);
|
||||
void jump(size_t pointer, void* data, bool use_far = false);
|
||||
void jump(size_t pointer, size_t data, bool use_far = false);
|
||||
void jump(void* pointer, void* data, bool use_far = false, bool use_safe = false);
|
||||
void jump(size_t pointer, void* data, bool use_far = false, bool use_safe = false);
|
||||
void jump(size_t pointer, size_t data, bool use_far = false, bool use_safe = false);
|
||||
|
||||
void* assemble(const std::function<void(assembler&)>& asm_function);
|
||||
|
||||
void inject(void* pointer, const void* data);
|
||||
void inject(size_t pointer, const void* data);
|
||||
|
||||
std::vector<uint8_t> move_hook(void* pointer);
|
||||
std::vector<uint8_t> move_hook(size_t pointer);
|
||||
|
||||
template <typename T>
|
||||
T extract(void* address)
|
||||
{
|
||||
@ -202,4 +212,4 @@ namespace utils::hook
|
||||
{
|
||||
return static_cast<T(*)(Args ...)>(func)(args...);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user