diff --git a/src/common/utils/hook.cpp b/src/common/utils/hook.cpp index be05cb96..3b89b471 100644 --- a/src/common/utils/hook.cpp +++ b/src/common/utils/hook.cpp @@ -230,12 +230,16 @@ namespace utils::hook return call(pointer, reinterpret_cast(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 +249,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 +267,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(pointer), data, use_far); + return jump(reinterpret_cast(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(data), use_far); + return jump(pointer, reinterpret_cast(data), use_far, use_safe); } void* assemble(const std::function& asm_function) @@ -297,6 +309,31 @@ namespace utils::hook return inject(reinterpret_cast(pointer), data); } + void move_hook(void* pointer) + { + auto* data_ptr = static_cast(pointer); + if (data_ptr[0] == 0xE9) + { + 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) + { + copy(data_ptr + 1, data_ptr, 0x14); + nop(data_ptr, 1); + } + else + { + throw std::runtime_error("No branch instruction found"); + } + } + + void move_hook(const size_t pointer) + { + return move_hook(reinterpret_cast(pointer)); + } + void* follow_branch(void* address) { auto* const data = static_cast(address); diff --git a/src/common/utils/hook.hpp b/src/common/utils/hook.hpp index bb24f8ce..bdaadcf3 100644 --- a/src/common/utils/hook.hpp +++ b/src/common/utils/hook.hpp @@ -10,20 +10,20 @@ namespace utils::hook { namespace detail { - template + template std::vector get_iota_functions() { - if constexpr (entries == 0) + if constexpr (Entries == 0) { std::vector functions; return functions; } else { - auto functions = get_iota_functions(); + auto functions = get_iota_functions(); functions.emplace_back([]() { - return entries - 1; + return Entries - 1; }); return functions; } @@ -36,7 +36,7 @@ namespace utils::hook // Example: // ID3D11Device* device = ... // auto entry = get_vtable_entry(device, &ID3D11Device::CreateTexture2D); - template + template 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(); + auto iota_functions = detail::get_iota_functions(); auto* object = iota_functions.data(); - using FakeFunc = size_t(__thiscall*)(void* self); - auto index = static_cast(pointer)(&object); + using fake_func = size_t(__thiscall*)(void* self); + auto index = static_cast(pointer)(&object); void** obj_v_table = *reinterpret_cast(obj); return &obj_v_table[index]; @@ -154,15 +154,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& asm_function); void inject(void* pointer, const void* data); void inject(size_t pointer, const void* data); + void move_hook(void* pointer); + void move_hook(size_t pointer); + template T extract(void* address) {