хук диалога

Vabots

Участник
Автор темы
73
5
Помогите с реализацией кода на C для установки хука на функцию в DLL. Или может будут у кого-то уже готовые примеры

Я работаю над проектом, который включает установку хука на функцию в DLL, и я хотел бы переписать свой Lua скрипт на C. Мой Lua скрипт использует FFI для установки хука на функцию в `samp.dll`. Вот как он выглядит:

Рабочий куд на луа для лука диалога:
local ffi = require("ffi")

ffi.cdef[[
    int VirtualProtect(void* lpAddress, unsigned long dwSize, unsigned long flNewProtect, unsigned long* lpflOldProtect);
]]

local hook = { hooks = {} }

function hook.new(cast, callback, hook_addr, size)
    jit.off(callback, true)
    local size = size or 5
    local new_hook = {}
    local detour_addr = tonumber(ffi.cast('intptr_t', ffi.cast('void*', ffi.cast(cast, callback))))
    local void_addr = ffi.cast('void*', hook_addr)
    local old_prot = ffi.new('unsigned long[1]')
    local org_bytes = ffi.new('uint8_t[?]', size)
    ffi.copy(org_bytes, void_addr, size)
    local hook_bytes = ffi.new('uint8_t[?]', size, 0x90)
    hook_bytes[0] = 0xE9
    ffi.cast('uint32_t*', hook_bytes + 1)[0] = detour_addr - hook_addr - 5
    new_hook.call = ffi.cast(cast, hook_addr)
    new_hook.status = false

    local function set_status(bool)
        new_hook.status = bool
        ffi.C.VirtualProtect(void_addr, size, 0x40, old_prot)
        ffi.copy(void_addr, bool and hook_bytes or org_bytes, size)
        ffi.C.VirtualProtect(void_addr, size, old_prot[0], old_prot)
    end

    new_hook.stop = function() set_status(false) end
    new_hook.start = function() set_status(true) end
    new_hook.start()

    table.insert(hook.hooks, new_hook)

    return setmetatable(new_hook, {
        __call = function(self, ...)
            self.stop()
            local res = self.call(...)
            self.start()
            return res
        end
    })
end

local samp = getModuleHandle("samp.dll")
local str = ffi.string
local originalCDialog_Show

local CDialog_ShowPrototype = 'void(__thiscall*)(void*, int, int, const char*, const char*, const char*, const char*, bool)'

function CDialog_Show(this, nId, nType, szCaption, szText, szLeftButton, szRightButton, bServerside)
    local caption = str(szCaption)
    local text = str(szText)
    local leftButton = str(szLeftButton)
    local rightButton = str(szRightButton)
    print("show dialog: ", nId, nType, caption, text, leftButton, rightButton, bServerside)
    return originalCDialog_Show(this, nId, nType, szCaption, szText, szLeftButton, szRightButton, bServerside)
end

originalCDialog_Show = hook.new(CDialog_ShowPrototype, CDialog_Show, samp + 0x6B9C0)

Мне нужно переписать этот код на C. В частности, я хочу:
1. Получать базовый адрес `samp.dll` с помощью `GetModuleHandle`.
2. Устанавливать и удалять хук на функцию в этой DLL.
3. Реализовать саму функцию хука на C.

Вот пример того, как я начал это делать на C:

Код на си:
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef void (__thiscall *CDialog_Show_t)(void*, int, int, const char*, const char*, const char*, const char*, int);

static CDialog_Show_t originalCDialog_Show = NULL;
static void* samp_base = NULL;

void set_hook(void* hook_addr, CDialog_Show_t new_func, size_t size) {
    DWORD old_protect;
    uint8_t* addr = (uint8_t*)hook_addr;
    uint8_t org_bytes[5];

    memcpy(org_bytes, addr, size);

    uint8_t hook_bytes[5] = {0xE9};
    *(uint32_t*)(hook_bytes + 1) = (uint32_t)((intptr_t)new_func - (intptr_t)hook_addr - 5);

    VirtualProtect(hook_addr, size, PAGE_EXECUTE_READWRITE, &old_protect);
    memcpy(addr, hook_bytes, size);
    VirtualProtect(hook_addr, size, old_protect, &old_protect);

    originalCDialog_Show = (CDialog_Show_t)org_bytes;
}

void __thiscall CDialog_Show(void* thisPtr, int nId, int nType, const char* szCaption, const char* szText, const char* szLeftButton, const char* szRightButton, int bServerside) {
    printf("show dialog: %d %d %s %s %s %s %d\n", nId, nType, szCaption, szText, szLeftButton, szRightButton, bServerside);

    originalCDialog_Show(thisPtr, nId, nType, szCaption, szText, szLeftButton, szRightButton, bServerside);
}

__declspec(dllexport) void init_hook(void* base_addr) {
    samp_base = base_addr;
    set_hook((void*)(samp_base + 0x6B9C0), CDialog_Show, 5);
}

Может кто-то помочь с завершением этого кода? Я хочу понять, как правильно использовать `VirtualProtect`, как корректно извлечь оригинальные байты и как управлять установкой и удалением хука.