Untitled

 avatar
unknown
plain_text
25 days ago
2.9 kB
7
Indexable
#include <Windows.h>
#include <cstdint>
#include <memory>
#include <cstring>

namespace StealthHook {

    struct HookContext {
        BYTE originalBytes[16];
        void* target;
        void* detour;
        void* trampoline;
        size_t patchSize;
    };

    void* AllocTrampoline(size_t size) {
        return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    }

    bool PlaceJMP(void* target, void* detour, BYTE* original, size_t len) {
        if (len < 5) return false;

        DWORD oldProtect;
        VirtualProtect(target, len, PAGE_EXECUTE_READWRITE, &oldProtect);
        memcpy(original, target, len);

#ifdef _WIN64
        if (std::abs((int64_t)detour - (int64_t)target) > 0x7FFFFFFF) {
            BYTE patch[14] = {
                0x48, 0xB8,
                0, 0, 0, 0, 0, 0, 0, 0,
                0xFF, 0xE0
            };
            memcpy(patch + 2, &detour, 8);
            memcpy(target, patch, 14);
            VirtualProtect(target, len, oldProtect, &oldProtect);
            return true;
        }
#endif

        uintptr_t relAddr = (uintptr_t)detour - (uintptr_t)target - 5;
        BYTE patch[16] = { 0xE9 };
        memcpy(patch + 1, &relAddr, 4);
        memcpy(target, patch, len);

        VirtualProtect(target, len, oldProtect, &oldProtect);
        return true;
    }

    bool CreateHook(void* target, void* detour, HookContext& ctx, size_t patchLen = 5) {
        if (!target || !detour || patchLen < 5 || patchLen > sizeof(ctx.originalBytes)) return false;

        ctx.target = target;
        ctx.detour = detour;
        ctx.patchSize = patchLen;
        memcpy(ctx.originalBytes, target, patchLen);

        ctx.trampoline = AllocTrampoline(patchLen + 5);
        if (!ctx.trampoline) return false;

        memcpy(ctx.trampoline, ctx.originalBytes, patchLen);
        uintptr_t jumpBack = (uintptr_t)target + patchLen;
        BYTE jmpBack[5] = { 0xE9 };
        uintptr_t rel = jumpBack - ((uintptr_t)ctx.trampoline + patchLen) - 5;
        memcpy(jmpBack + 1, &rel, 4);
        memcpy((BYTE*)ctx.trampoline + patchLen, jmpBack, 5);

        DWORD trampProtect;
        VirtualProtect(ctx.trampoline, patchLen + 5, PAGE_EXECUTE_READ, &trampProtect);

        return PlaceJMP(target, detour, ctx.originalBytes, patchLen);
    }

    void RemoveHook(HookContext& ctx) {
        if (!ctx.target) return;
        DWORD oldProtect;
        VirtualProtect(ctx.target, ctx.patchSize, PAGE_EXECUTE_READWRITE, &oldProtect);
        memcpy(ctx.target, ctx.originalBytes, ctx.patchSize);
        VirtualProtect(ctx.target, ctx.patchSize, oldProtect, &oldProtect);
    }

    template<typename T>
    T GetOriginal(HookContext& ctx) {
        return reinterpret_cast<T>(ctx.trampoline);
    }

} // namespace StealthHook
Editor is loading...
Leave a Comment