Hook技术
1 什么是Hook,这个概念应该从何说起???
Hook:是钩子的意思
Hook技术主要指的是拦截程序原有的信息,数据,代码,
1 使得你有机会对拦截到的信息数据做处理。然后再交给原来的程序去使用,从而能够截获到程序的关键信息。可以查看,也可以修改。
2 能够修改程序的部分功能。
2 Hook是怎么分类的??
在windows系统下,有两类Hook:
2.1 windows消息Hook。windows提供的能够让程序员截获到所有窗口程序消息的机制。
消息Hook也是我们的一种Dll注入手段。
2.2 自定义Hook 非常普遍的Hook方式,也是我们通常意义所说的Hook。
2.2.1 修改程序的代码,使得其能够执行到Hook者提供的“善意代码”中。 inline-Hook
2.2.2 修改存储函数地址的变量,当程序从变量中获取函数地址并调用的时候,就会调用到Hook者提供的“善意代码”了。
IAT-Hook
IDT-Hook
SYSENTR-Hook
3 windows消息钩子的实现的原理以及代码
3.1 windows消息钩子的实现的原理
SetWindowsHookEx这个函数,能够实现的功能是截获
1 系统中所有的窗口程序的消息或者
2 某一个线程的窗口消息。
截获到了消息,必然是需要执行自己的代码,自己的代码需要放置在一个dll中,然后消息钩子设置成功之后,会将dll注入到目标进程,从而使得自己的回调函数能够在对方的进程中执行。
额外的知识点:窗口程序的消息是被某一个线程获取到的,哪一个线程创建了窗口,哪一个线程就能够获得此窗口的消息。此线程在创建完窗口之后,就变成了GUI线程。
HHOOK SetWindowsHookExA(
int idHook, 要截获的是哪种类型的消息
HOOKPROC lpfn, 截获到消息之后,调用的回调函数
HINSTANCE hmod, 回调函数所在的模块,这个模块需要是一个dll。
DWORD dwThreadId 填0 截获系统中所有的窗口的消息 填线程ID 那就仅截获此线程的窗口消息
);
//当钩子使用完毕之后,卸载钩子
BOOL WINAPI UnhookWindowsHookEx(
_In_ HHOOK hhk //填充返回的句柄
);
在钩子的消息拦截函数的最后,应该调用这个函数,因为程序可能会有多个钩子,新添加的在最上面,为了不影响其他钩子的功能,需要调用这个函数。
WINUSERAPI
LRESULT
WINAPI
CallNextHookEx(
_In_opt_ HHOOK hhk, //钩子的句柄
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam);
3.1 消息钩子的代码
#define _countof(a) sizeof(a)/sizeof(a[0])
HHOOK g_Hook = 0;
//拦截消息的回调函数
LRESULT CALLBACK KeyboardProc(
int code, // 消息类型
WPARAM wParam, // 虚拟码
LPARAM lParam) { // 按键信息
// 判断是否wParam与lParam都有键盘消息,是的话则执行打印操作
if (code == HC_ACTION) {
// 将256个虚拟键的状态拷贝到指定的缓冲区中,如果成功则继续
BYTE KeyState[256] = { 0 };
if (GetKeyboardState(KeyState)) {
// 得到第16–23位,键盘虚拟码
LONG KeyInfo = lParam;
UINT keyCode = (KeyInfo >> 16) & 0x00ff;
WCHAR wKeyCode = 0;
ToAscii((UINT)wParam, keyCode, KeyState, (LPWORD)&wKeyCode, 0);
// 将其打印出来
WCHAR szInfo[512] = { 0 };
swprintf_s(szInfo, _countof(szInfo), L"Hook_%c", (char)wKeyCode);
OutputDebugString(szInfo);
return 0;
}
}
return CallNextHookEx(g_Hook, code, wParam, lParam);
}
//开启Hook的函数
void OnHook()
{
HMODULE hModule = GetModuleHandle(L"MessageHookdll.dll");
g_Hook = SetWindowsHookEx(
WH_KEYBOARD,
KeyboardProc,
hModule,
NULL
);
}
//关闭Hook的函数
void UnHook()
{
if (g_Hook!=0)
{
UnhookWindowsHookEx(g_Hook);
g_Hook = 0;
}
}
被拦截到消息的程序,也被注入了dll。
4 自定义钩子:
自定义钩子两大类:内联钩子 修改存储函数地址变量的钩子
4.1 什么是内联钩子 inline-Hook
任何位置,都可以修改为jmp,使其执行到此处时,能够跳转到我们自己的代码去执行:
1 被修改的指令,是否是有用的,如果是有用的,那么你就需要在你自己的代码中,将有用的指令写一遍,使其在你代码中能够执行。
2 jmp指令一般是5个字节,所以我们选取的指令最好也是5个字节,如果不是5个字节,那么会发生指令截断,跳转回来的时候,就需要考虑跳转到完整的指令后去执行程序本身的代码。
3 jmp指令OPCODE的操作数怎么求得,也是Hook的关键知识点
jmp指令OPCODE的操作数 = 要跳转的目标地址-hook点所在的地址-5
–转载15pb高老师