42 lines
1.6 KiB
C++
42 lines
1.6 KiB
C++
#include <FunctionHook/Hook.h>
|
|
#include <sys/mman.h>
|
|
#include <csignal>
|
|
#include <cstring>
|
|
|
|
constexpr uint32_t JAL_OPCODE = 0b1101111;
|
|
constexpr int JAL_OFFSET_SHIFT = 12;
|
|
constexpr int JAL_MASK = 0xfff;
|
|
|
|
void FunctionHooking::Detour::CreateHook(void* source_address, void* destination_address) {
|
|
intptr_t target_addr = reinterpret_cast<intptr_t>(source_address);
|
|
intptr_t hook_addr = reinterpret_cast<intptr_t>(destination_address);
|
|
int32_t offset = (hook_addr - target_addr) >> 1;
|
|
|
|
// Encode the offset for the JAL instruction
|
|
uint32_t instruction = (JAL_OPCODE & JAL_MASK) |
|
|
((offset & 0x7fe) << 20) | // bits 1 to 10 of offset
|
|
((offset & 0x800) << 9) | // bit 11 of offset
|
|
((offset & 0xff000) << 9); // bits 12 to 19 of offset
|
|
|
|
hook_bytes.resize(sizeof(instruction));
|
|
std::memcpy(hook_bytes.data(), &instruction, sizeof(instruction));
|
|
|
|
overwritten_bytes.resize(sizeof(instruction));
|
|
std::memcpy(overwritten_bytes.data(), source_address, sizeof(instruction));
|
|
|
|
// Determine the page size and page containing the target function
|
|
long page_size = sysconf(_SC_PAGESIZE);
|
|
void* page_start = reinterpret_cast<void*>(target_addr & ~(page_size - 1));
|
|
|
|
// Change memory protection to allow writing
|
|
if (mprotect(page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
|
|
return;
|
|
|
|
// Write the instruction to the target function
|
|
std::memcpy(source_address, &instruction, sizeof(instruction));
|
|
|
|
// Restore original memory protection
|
|
if (mprotect(page_start, page_size, PROT_READ | PROT_EXEC) == -1)
|
|
return;
|
|
}
|