Add required hooking extensions
This commit is contained in:
parent
0dabe137cb
commit
feb1282e03
@ -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");
|
||||||
@ -244,10 +248,18 @@ namespace utils::hook
|
|||||||
auto* patch_pointer = PBYTE(pointer);
|
auto* patch_pointer = PBYTE(pointer);
|
||||||
|
|
||||||
if (use_far)
|
if (use_far)
|
||||||
|
{
|
||||||
|
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, jump_data, sizeof(jump_data));
|
||||||
copy(patch_pointer + 2, &data, sizeof(data));
|
copy(patch_pointer + 2, &data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set<uint8_t>(patch_pointer, 0xE9);
|
set<uint8_t>(patch_pointer, 0xE9);
|
||||||
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user