Add required hooking extensions

This commit is contained in:
momo5502 2022-05-23 17:57:29 +02:00
parent 0dabe137cb
commit feb1282e03
2 changed files with 58 additions and 18 deletions

View File

@ -230,12 +230,16 @@ namespace utils::hook
return call(pointer, reinterpret_cast<void*>(data)); 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[] = { static const unsigned char jump_data[] = {
0x48, 0xb8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xff, 0xe0 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)) if (!use_far && is_relatively_far(pointer, data))
{ {
throw std::runtime_error("Too far away to create 32bit relative branch"); throw std::runtime_error("Too far away to create 32bit relative branch");
@ -245,8 +249,16 @@ namespace utils::hook
if (use_far) if (use_far)
{ {
copy(patch_pointer, jump_data, sizeof(jump_data)); if (use_safe)
copy(patch_pointer + 2, &data, sizeof(data)); {
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 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<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) void* assemble(const std::function<void(assembler&)>& asm_function)
@ -297,6 +309,31 @@ namespace utils::hook
return inject(reinterpret_cast<void*>(pointer), data); return inject(reinterpret_cast<void*>(pointer), data);
} }
void move_hook(void* pointer)
{
auto* data_ptr = static_cast<uint8_t*>(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<void*>(pointer));
}
void* follow_branch(void* address) void* follow_branch(void* address)
{ {
auto* const data = static_cast<uint8_t*>(address); auto* const data = static_cast<uint8_t*>(address);

View File

@ -10,20 +10,20 @@ namespace utils::hook
{ {
namespace detail namespace detail
{ {
template<size_t entries> template <size_t Entries>
std::vector<size_t(*)()> get_iota_functions() std::vector<size_t(*)()> get_iota_functions()
{ {
if constexpr (entries == 0) if constexpr (Entries == 0)
{ {
std::vector<size_t(*)()> functions; std::vector<size_t(*)()> functions;
return functions; return functions;
} }
else else
{ {
auto functions = get_iota_functions<entries - 1>(); auto functions = get_iota_functions<Entries - 1>();
functions.emplace_back([]() functions.emplace_back([]()
{ {
return entries - 1; return Entries - 1;
}); });
return functions; return functions;
} }
@ -36,7 +36,7 @@ namespace utils::hook
// Example: // Example:
// ID3D11Device* device = ... // ID3D11Device* device = ...
// auto entry = get_vtable_entry(device, &ID3D11Device::CreateTexture2D); // auto entry = get_vtable_entry(device, &ID3D11Device::CreateTexture2D);
template <size_t entries = 100, typename Class, typename T, typename... Args> template <size_t Entries = 100, typename Class, typename T, typename... Args>
void** get_vtable_entry(Class* obj, T (Class::* entry)(Args ...)) void** get_vtable_entry(Class* obj, T (Class::* entry)(Args ...))
{ {
union union
@ -47,11 +47,11 @@ namespace utils::hook
func = entry; func = entry;
auto iota_functions = detail::get_iota_functions<entries>(); auto iota_functions = detail::get_iota_functions<Entries>();
auto* object = iota_functions.data(); auto* object = iota_functions.data();
using FakeFunc = size_t(__thiscall*)(void* self); using fake_func = size_t(__thiscall*)(void* self);
auto index = static_cast<FakeFunc>(pointer)(&object); auto index = static_cast<fake_func>(pointer)(&object);
void** obj_v_table = *reinterpret_cast<void***>(obj); void** obj_v_table = *reinterpret_cast<void***>(obj);
return &obj_v_table[index]; return &obj_v_table[index];
@ -154,15 +154,18 @@ namespace utils::hook
void call(size_t pointer, void* data); void call(size_t pointer, void* data);
void call(size_t pointer, size_t data); void call(size_t pointer, size_t data);
void jump(void* pointer, void* 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); 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); 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* assemble(const std::function<void(assembler&)>& asm_function);
void inject(void* pointer, const void* data); void inject(void* pointer, const void* data);
void inject(size_t pointer, const void* data); void inject(size_t pointer, const void* data);
void move_hook(void* pointer);
void move_hook(size_t pointer);
template <typename T> template <typename T>
T extract(void* address) T extract(void* address)
{ {