Исходник HHelper (x86) - single header library for easier hooking

kin4stat

mq-team
Автор темы
Всефорумный модератор
2,731
4,692

HHelper (x86)​

Небольшая библиотека для упрощения работы с хуками при выгрузке.
Больше не нужно заботиться о снятии хуков
Библиотека имеет настраеваемые типы для вызова оригинальной функции, и функции трамплина. Перед трамплином можно выделить немного памяти для некоторых манипуляций.


Немного примеров кода:​

Хук обычной функции:
static HookHelper helper(&HookFunction);
MH_CreateHook(functionPointer, helper.GetInstructionPointer(), &Trampoline);
MH_EnableHook(functionPointer);
helper.SetTrampoline(Trampoline);
Output:
jmp 01C42C0A
jmp 01910FE0
jmp ASIPlugin.asi+11168
В данном случае после опкода вызова функции ret будет поставлен автоматически:

WNDPROC:
WNDPROC m_pWindowProc;

LRESULT __stdcall WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    return CallWindowProcA(m_pWindowProc, hWnd, msg, wParam, lParam);
}

void InstallWndProcHook() {
    static HookHelper helper(&WndProcHandler, CallType::JMP, CallType::CALL);
    m_pWindowProc = reinterpret_cast<WNDPROC>(SetWindowLongW(hWnd, GWL_WNDPROC, reinterpret_cast<LONG>(helper.GetInstructionPointer())));
    helper.SetTrampoline(GetProcAddress(GetModuleHandleA("user32.dll"), "CallWindowProcA"), CallWindowProcA, 1);
    helper.PushBytesRightBeforeCall('\x68'); // Opcode::PUSH
    helper.PushBytesRightBeforeCall(m_pWindowProc);
}
WNDPROC:
WNDPROC m_pWindowProc;

LRESULT __stdcall WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    return CallWindowProcA(m_pWindowProc, hWnd, msg, wParam, lParam);
}
void InstallWndProcHook() {
    const char Pushes[] = {
        "\xFF\x74\x24\x10" // push [esp + 0x10]
        "\xFF\x74\x24\x10" // push [esp + 0x10]
        "\xFF\x74\x24\x10" // push [esp + 0x10]
        "\xFF\x74\x24\x10" // push [esp + 0x10]
        "\x68" }; // push
    auto push_size = sizeof(Pushes) - 1;
    static HookHelper helper(&WndProcHandler,  push_size + 5, Pushes, push_size, CallType::JMP, CallType::CALL);
    auto HandlerPointer = reinterpret_cast<LONG>(helper.GetInstructionPointer()));
    m_pWindowProc = reinterpret_cast<WNDPROC>(SetWindowLongW(hWnd, GWL_WNDPROC, HandlerPointer);
    helper.SetAdditionalBytes(m_pWindowProc);
    helper.SetTrampoline(GetProcAddress(GetModuleHandleA("user32.dll"), "CallWindowProcA"));
}
Output:
jmp 132EC420
push [esp+10]
push [esp+10]
push [esp+10]
push [esp+10]
push ___mainthing.asi+2430
call USER32.CallWindowProcA
ret
jmp ASIPlugin.asi+113E8



Небольшое описание методов:​

Конструктор HookHelper - Принимает указатель на функцию для которой создается прослойка, и типы вызовов для функции на которую создается прослойка и функции-трамплина
GetInstructionPointer - Создает в памяти саму прослойку, ее нужно использовать вместо функции, которую вы хотели использовать вместо хука
SetTrampoline - Ставит прыжок на функцию-трамплин, имеет перегрузку которая принимает прототип функции и количество аргументов которые вы будете обрабатывать самостоятельно. Прототип функции нужен для автоматической генерации кода пробрасывающего аргументы в трамплин.
manual_args_count - количество аргументов которое будет обработано вами. Можно увидеть использование во втором примере.
PushBytesRightBeforeCall - передает ваши данные в прослойку ПРЯМО перед вызовом. Имеет две перегрузки, одна принимает массив байт и его размер, вторая - любые данные. Использование можно увидеть во втором примере
PushBytesBeforeCall - передает ваши данные в прослойку перед вызовом, но не гаратируется что они будут расположены непосредственно перед вызовом, имеет такие же две перегрузки как и PushBytesRightBeforeCall.

Как это работает?​

Библиотека создает код-прослойку. До отгрузки будет производиться прыжок в оригинальную функцию, после отгрузки - в трамплин.


Download & Source:
 
Последнее редактирование:

kin4stat

mq-team
Автор темы
Всефорумный модератор
2,731
4,692
Обновил.
Добавил документацию в самом коде, и на форуме.
Также небольшие улучшения в коде, ну а также более удобный интерфейс. Теперь пробрасывать функции стало еще удобнее. Сравнить можно в примерах WNDPROC