windows hook - inline hook

inline hook 内联钩子是一种常用的钩子

其原理是直接把函数开头改成一个JMP ,后跟我们的hook函数地址

在hook函数里就随后恢复我们的原始字节 并跳到原函数执行 随后直接再次改成JMP挂钩

一般来说在windows内程序代码应该都是不可写的 需要使用VirtualProtect函数来改权限

BOOL
WINAPI
VirtualProtect(
    _In_  LPVOID lpAddress,
    _In_  SIZE_T dwSize,
    _In_  DWORD flNewProtect,
    _Out_ PDWORD lpflOldProtect
    )
{
    return VirtualProtectFromApp (lpAddress, dwSize, flNewProtect, lpflOldProtect);
}

简单的poc

#include <iostream>
#include <windows.h>

BYTE original_code[14];
void hook(ULONG_PTR addr, ULONG_PTR target);
void unhook(ULONG_PTR addr, BYTE* original);

int print_custom() {
    std::cout << "Hello World!\n";
    return 0;
}

int print_hook() {
    std::cout << "you are hooked!" << std::endl;
    unhook((ULONG_PTR)&print_custom, original_code);
    print_custom();
    hook((ULONG_PTR)&print_custom, (ULONG_PTR)&print_hook);
    return 0;
}



int main()
{
    ULONG_PTR print_addr = (ULONG_PTR)&print_custom;
    std::cout <<"[+]print_addr=>" << std::hex << print_addr << std::endl;
    ULONG_PTR print_hook_addr = (ULONG_PTR)&print_hook;
    std::cout << "[+]print_hook=>" << std::hex << print_hook_addr << std::endl;

    DWORD dwOldProtect;


    VirtualProtect((LPVOID)print_addr, 0x233, 64, &dwOldProtect);
    memcpy((void*)(&original_code), (void*)(print_addr), 14);
    hook(print_addr, print_hook_addr);
    
    int qwq = print_custom();
    int qwq1 = print_custom();
    system("pause");

}

void hook(ULONG_PTR addr,ULONG_PTR target){
    BYTE jmp_code[14] = {
   0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,  // ; jmp qword ptr [rip + 0x0]
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // 后跟绝对地址
    };
    memcpy((void*)&jmp_code[6], (void*)&target, 8);
    memcpy((void*)(addr), &jmp_code, 14);
}

void unhook(ULONG_PTR addr, BYTE* original) {
    memcpy((void*)addr, original, 14);
}