#pragma once #include #include #include #include #include #include using namespace std; vector make_trampoline(uintptr_t orig,uintptr_t hook) { using namespace asmjit; vector ret; JitRuntime rt; CodeHolder code; CodeInfo ci=rt.codeInfo(); code.init(ci); x86::Assembler a(&code); a.jmp(hook); a.ret(); code.flatten(); code.resolveUnresolvedLinks(); code.relocateToBase(orig); size_t code_size=code.sectionById(0)->buffer().size(); uint8_t* buffer=new uint8_t[code_size]; code.copyFlattenedData((void*)buffer, code_size, CodeHolder::kCopyWithPadding); for (size_t i=0;i> hooks; public: Hook(void *func, void *detour) { uintptr_t dest = reinterpret_cast(detour); uintptr_t src = reinterpret_cast(func); this->orig = func; this->detour = detour; vector code = make_trampoline(src,dest); this->orig_bytes = new uint8_t[code.size()]; this->jmp_bytes = new uint8_t[code.size()]; this->size = code.size(); this->enabled = false; uint8_t* func_b = reinterpret_cast(this->orig); for (size_t i=0;isize;++i) { this->orig_bytes[i]=func_b[i]; this->jmp_bytes[i]=code[i]; } VirtualQuery(this->orig, &mbi, sizeof(mbi)); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); cout<<"Constructed hook from "<size<orig << " <- " << this->detour << "]" << endl; this->disable(); } static void addr(uintptr_t _addr, void *detour) { Hook::addr(reinterpret_cast(_addr),detour); } static void addr(void *addr, void *detour) { cout << "Hooking: [" << addr << " -> " << detour << "]" << endl; uintptr_t key = reinterpret_cast(detour); hooks[key] = make_shared(addr, detour); hooks[key]->enable(); } static void module(const char *mod, const char *func, void *detour) { cout << "Hooking: [" << mod << "]." << func << " -> " << detour << endl; void *addr = GetProcAddress(GetModuleHandle(mod), func); if (addr != NULL) { Hook::addr(addr, detour); } else { cerr << "[" << mod << "]." << func << " not found!" << endl; }; } static shared_ptr get(void *func) { uintptr_t addr = reinterpret_cast(func); return Hook::get(addr); } static shared_ptr get(uintptr_t addr) { return hooks.at(addr); } static size_t drop(void *func) { uintptr_t addr = reinterpret_cast(func); return Hook::drop(addr); } static size_t drop(uintptr_t addr) { return hooks.erase(addr); } static void clear() { cout << "Clearing Hooks" << endl; for (pair> h : hooks) { h.second->disable(); } return hooks.clear(); } void disable() { if (this->enabled) { cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl; VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); memcpy(this->orig, this->orig_bytes, this->size); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); this->enabled = false; } } void enable() { if (!this->enabled) { cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl; VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); memcpy(this->orig, this->jmp_bytes, this->size); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); this->enabled = true; } } template void func_void(Args... args) { this->disable(); reinterpret_cast(this->orig)(args...); this->enable(); return; } template auto func(Args... args) { this->disable(); auto ret = reinterpret_cast(this->orig)(args...); this->enable(); return ret; } }; map> Hook::hooks;