Relocation
Replace call/jmp instruction with a hook.
Syntax
cpp
RelHookHandle Hook::AddRelHook<N, bool>(address, function);Parameter
N: length of target instruction, e.g.call Game.exe+0x1999DFisE8 0C 77 FA FF, which is 5 bytes in length.FF 15 12 34 56 78is 6 bytes.bool: whether to return or not,callreturns,jmpbranches thus no return.address: target instruction address.function: hook function.
HookHandle
A RelHookHandle object will be returned:
cpp
class RelHookHandle
{
const std::size_t OpSeqSize;
const Imm64 OriginalFunc;
Imm64 Destination;
std::vector<OpCode> OldBytes{};
std::vector<OpCode> Detour{};
};RelHookHandle can be implicitly convereted to address of original function.
Wrapper
For the ease of use, you can use Hook::write_call<N> and Hook::write_branch<N> for convenience. These wrappers will enable itself and return the original function address. However, you lose control of disabling the hook.
Example
Given target assembly:
asm
0x140345675: mov rcx, rax
0x140345678: call Game.exe+0x123456We want to replace the call Game.exe+0x123456 to call HookFunc:
cpp
class Hook
{
// hook function
static bool Hook_123456(void* a_instance)
{
// do something
return func(a_instance);
}
// original function
static inline std::add_pointer_t<decltype(Hook_123456)> func;
public:
static void Install()
{
// absolute
auto addr = 0x7FF712345678;
// or offset from module base
auto addr = dku::Hook::Module::get().base() + 0x345678;
// save original function
func = dku::Hook::write_call<5>(addr, Hook_123456);
}
};cpp
// forward
bool Hook_123456(void* a_instance);
// original function
std::add_pointer_t<decltype(Hook_123456)> func;
bool Hook_123456(void* a_instance)
{
// do something
return func(a_instance);
}
auto addr = dku::Hook::Module::get().base() + 0x345678;
// save original function
func = dku::Hook::write_call<5>(addr, Hook_123456);