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);
}