Исходник [C++] Custom Hooks

ЯedЯuM

Malware Maker
Автор темы
244
304
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Сделано для тех кто не любит таскать за собой целые библиотеки хуков.
Благодаря возможности указывать размер пролога, можно хукать как WIN API так и пользовательские функции.
Присутствует трамплин.
C++:
DWORD MakeJump(DWORD jmp_address, DWORD hookAddr, byte *prologue, size_t prologue_size)
{
    DWORD old_prot = 0x0;
    if (prologue == nullptr) return 0x0;
    VirtualProtect((void*)jmp_address, prologue_size, PAGE_EXECUTE_READWRITE, &old_prot);
    memcpy(prologue, (void*)jmp_address, prologue_size);
    byte addrToBytes[5] = { 0xE9, 0x90, 0x90, 0x90, 0x90 };
    DWORD JMPBytes = (hookAddr - jmp_address - 5);
    memcpy(&addrToBytes[1], &JMPBytes, 4);
    memcpy((void*)jmp_address, addrToBytes, 5);
    PVOID Trampoline = VirtualAlloc(0, (5 + (prologue_size - 5)), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    byte TrampolineBytes[5] = { 0xE9, 0x90, 0x90, 0x90, 0x90 };
    if (prologue_size > 5)
    {
        byte nop[] = { 0x90 };
        for (byte x = 0; x < (prologue_size - 5); x++) memcpy((void*)(jmp_address + 0x5 + x), nop, 1);
        memcpy(Trampoline, &prologue[3], (prologue_size - 3));
        DWORD Delta = (jmp_address + prologue_size) - (((DWORD)Trampoline + (prologue_size - 3)) + 5);
        memcpy(&TrampolineBytes[1], &Delta, 4);
        memcpy((void*)((DWORD)Trampoline + (prologue_size - 3)), TrampolineBytes, 5);
    }
    else
    {
        DWORD Delta = (jmp_address + prologue_size) - ((DWORD)Trampoline + 5);
        memcpy(&TrampolineBytes[1], &Delta, 4);
        memcpy(Trampoline, TrampolineBytes, 5);
    }
    VirtualProtect((void*)jmp_address, prologue_size, old_prot, 0);
    return (DWORD)Trampoline;
}
bool RestorePrologue(DWORD addr, byte *prologue, size_t prologue_size)
{
    if (prologue == nullptr) return false;
    DWORD old_prot = 0;
    VirtualProtect((void*)addr, prologue_size, PAGE_EXECUTE_READWRITE, &old_prot);
    memcpy((void*)addr, prologue, prologue_size);
    VirtualProtect((void*)addr, prologue_size, old_prot, &old_prot);
    return true;
}
Пример установки и удаления хука
C++:
DWORD Trampoline = 0x0; byte prologue[5];
void __stdcall UserHook(DWORD access, BOOL inherit, DWORD procID)
{
    printf("Hooked: %d\n", procID);
    __asm jmp Trampoline
}
void InstallAndDeleteHook()
{
    DWORD Addr = (DWORD)GetProcAddress(GetModuleHandleA("kernel32.dll"), "OpenProcess");
    Trampoline = MakeJump(Addr, (DWORD)&UserHook, prologue, 5); // Устанавливаем
    RestorePrologue(Addr, prologue, 5); // Удаляем
}
Автор: ЯedЯuM
 

ЯedЯuM

Malware Maker
Автор темы
244
304
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
А для чего нужен пролог?
Пролог это начало функции (push ebp, mov ebp, esp и тд), Эпилог её конец(перед возвратом).
Само понятие на сколько знаю пришло из ассемблера.
Просто если поставить хук, на прыжок требуется 5 байт, в вин апи почти в каждой стоит в самом начале инструкция mov edi, edi и вместе с push ebp, mov ebp, esp код как раз столько же и весит. А в случае с пользовательскими функциями к примеру, после mov ebp, esp может не быть инструкции размером в два байта, в итоге получится что хук затрёт два байта от той инструкции и она разобьется на другой код который будет уже не валид, возврат трамплином в такой код спровоцирует краш, вот почему нужно учитывать размер пролога функции, потому что инструкции push ebp, mov ebp, esp весят только 3 байта чего не достаточно для jmp инструкции прыжка на хук.

@Stiopko вот пример с пояснением как знать сколько байт указывать в размер пролога
Безымянный.png

Нам нужно занопить лишний байт, по этому указываем размер хука в 6 байт и тот байт 08 переставит на 90 (nop - ничего не делающая инструкция).
Безымянный.png

А вот наглядный пример для чего нужен трамплин а он нужен не только для возврата в оригинальную функцию.
Безымянный.png
 
Последнее редактирование: