#pragma once #define CalculateRelativeJMPAddress(X, Y) (((std::uintptr_t)Y - (std::uintptr_t)X) - 5) namespace utils::hook { class signature final { public: struct container final { std::string signature; std::string mask; std::function callback; }; signature(void* start, const size_t length) : start_(start), length_(length) { } signature(const DWORD start, const size_t length) : signature(reinterpret_cast(start), length) { } signature() : signature(0x400000, 0x800000) { } void process(); void add(const container& container); private: void* start_; size_t length_; std::vector signatures_; }; class detour { public: detour() = default; detour(void* place, void* target); detour(size_t place, void* target); ~detour(); detour(detour&& other) noexcept { this->operator=(std::move(other)); } detour& operator= (detour&& other) noexcept { if (this != &other) { this->~detour(); this->place_ = other.place_; this->original_ = other.original_; other.place_ = nullptr; other.original_ = nullptr; } return *this; } detour(const detour&) = delete; detour& operator= (const detour&) = delete; void enable() const; void disable() const; void create(void* place, void* target); void create(size_t place, void* target); void clear(); template T* get() const { return static_cast(this->get_original()); } template T invoke(Args... args) { return static_cast(this->get_original())(args...); } [[nodiscard]] void* get_original() const; private: void* place_{}; void* original_{}; }; void nop(void* place, size_t length); void nop(size_t place, size_t length); void copy(void* place, const void* data, size_t length); void copy(size_t place, const void* data, size_t length); bool is_relatively_far(const void* pointer, const void* data, int offset = 5); void call(void* pointer, void* data); void call(size_t pointer, void* data); void call(size_t pointer, size_t data); void jump(std::uintptr_t address, void* destination); template T extract(void* address) { const auto data = static_cast(address); const auto offset = *reinterpret_cast(data); return reinterpret_cast(data + offset + 4); } template static void set(void* place, T value) { DWORD old_protect; VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &old_protect); *static_cast(place) = value; VirtualProtect(place, sizeof(T), old_protect, &old_protect); FlushInstructionCache(GetCurrentProcess(), place, sizeof(T)); } template static void set(const size_t place, T value) { return set(reinterpret_cast(place), value); } template static T invoke(size_t func, Args... args) { return reinterpret_cast(func)(args...); } template static T invoke(void* func, Args... args) { return static_cast(func)(args...); } }