[Windows核心编程学习笔记] HOOK条目

HOOK学习笔记

一、概述

所有电话我都出来了,终于开始学习Win32HOOK机制了。尽管HOOK在很长一段时间内不是一项新技术hook编程,但这是我第一次接触它。以前,我只是从检测特洛伊木马的角度上才对HOOK有所了解。由于我从未真正接触过,因此缺少许多知识模块。作为关于HOOK的第一个学习笔记,我将简要介绍HOOK的基本知识,然后给出一个通过控制台实现的简单键盘挂钩示例。该注释的结构如下:

lWindows消息机制

lWindowsHOOK机制(全局HOOK)

lCore函数

l简单的程序示例

l问题

二、 Windows消息机制

Windows操作系统建立在事件驱动机制上,并且系统各个部分之间的通信也通过消息的相互传输来实现。但是在正常情况下,如果需要传输,应用程序只能处理来自进程内部的消息或其他进程发送的消息(借助于进程间通信技术,例如剪贴板,管道ag真人 ,邮件槽等)。流程之外必须采用一种称为HOOK的技术来拦截消息。 HOOK是Windows操作系统中非常重要的系统界面。它可以轻松地拦截和处理在其他应用程序之间传递的消息,从而可以完成一些普通应用程序难以实现的特殊功能。首先,让我们向不熟悉Windows编程的学生简要介绍Windows的消息机制。

我们知道Windows系统所有部分的通信都是通过发送消息来进行的,这实际上是一个MSG结构:

typedefstructtagMSG {

HWNDhwnd;

UINT消息;

WPARAMwParam;

LPARAMlParam;

DWORDtime;

POINTpt;

}味精;

对特定用法感兴趣的学生可以检查MSDN,这是一个冗长的句子,可以学习Windows编程

我的朋友们仍然必须下载MSDN,使用起来真的很方便。一般过程是,当系统I / O上发生事件时,系统捕获该事件并将消息发送到指定应用程序的消息队列。应用程序从消息队列中依次取出一条消息,并将其分派到系统以分派相应的消息。用于消息处理的窗口回调程序。在这里,我们给出了一个结构图,供大家理解。

hook编程

在这里,您可以看到从OS捕获消息并开始处理它,最后将其返回给OS以安排回调函数,就像遍历循环一样。我了解这是为什么将其称为“回调函数”的原因之一。我们要做的下一个HOOK是上面第二步和第三步之间的额外工作。

三、 WindowsHOOK机制

HOOK的本质是用于处理系统消息并通过系统调用将其挂接到系统中的程序。挂钩有很多类型,每个挂钩负责拦截和处理相应的消息。挂钩机制允许应用程序拦截和处理发送到指定窗口的消息或特定事件。监视的窗口可以在当前进程中,也可以在其他进程中创建。在发送特定消息并到达目标窗口之前,HOOK程序将截获该消息并获得对该消息的控制权。此时,可以在挂钩函数中对截获的消息进行各种修改,甚至可以强制终止消息的继续发送。

一开始我不了解的是,HOOK的数量是根据HOOK的类型进行划分的,例如WH_MOUSE,WH_KEYBOARD等。但是每个HOOK基本上由系统维护一个指针列表。指针指向HOOK的各种处理功能快乐赛车 ,我们将其称为HOOK子例程。调用SetWindowsHookEx()时,将在HOOK链的开头安装一个新的HOOK过程。有时当它不影响理解时,我们也说安装了一个新的HOOK。最早的HOOK放在链接列表的末尾(有点类似于堆栈)。当出现由HOOK监视的消息时,操作系统将在链接列表的开头调用第一个HOOK子例程进行处理,即,最后添加的HOOK具有优先权以获得控制权。此处的HOOK处理函数必须是回调函数,并且不能定义为类成员函数,它必须是普通的C函数。使用挂钩时,根据其监视范围可以将它们分为全局挂钩和线程挂钩。线程挂钩指定特定的线程ID(可以是当前线程),并且只能监视该线程。全局挂钩可以是监视一个窗口下的所有线程。这里的全局HOOK的本质是,触发HOOK机制的线程在其自己的进程空间中调用代码进行处理,因此我们的HOOK子例程代码必须映射到线程所在的进程的地址空间中,即,由DLL实现。为了使每个人都更容易理解,我们在此处还提供了一个图标:

首先我们编写HOOK驱动程序,将HOOK.dll映射到内存中,安装HOOK之后,执行HOOK监视:

hook编程

四、核心功能

使用WindowsHOOK不需要太多核心功能,只有四个:

SetWindowsHookEx():安装一个HOOK

HOOK子例程:HOOK处理功能,例如GetMsgProc,KeyboardProc等。

CallNextHookEx():调用HOOK链的下一个HOOK子例程

UnhookWindowsHookEx():卸载HOOK

HHOOKSetWindowsHookEx(

intidHook,

HOOKPROClpfn,

HINSTANCEhMod,

DWORDdwThreadId

);

第一个参数idHook用于标识HOOK类型,例如用于鼠标信息的WH_MOUSE,用于键盘消息的WH_KEYBOARD等。有关更多参数和功能,请参考MSDN

第二个参数lpfn指向特定的HOOK子例程,该子例程用于实际处理截获的消息

第三个参数hMod用于标识HOOK子例程所在的模块。如果它是一个全局HOOK,则它是一个加载到内存中的DLL句柄(使用GetModuleHandle获取);如果它是内部线程HOOK,则为NULL。可以。

第四个参数dwThread指定HOOK的范围。如果为0,则表示监视在同一窗口中运行的所有线程,否则,请指定特定的线程ID。

BOOLUnhookWindowsHookEx(

HHOOKhhk

);

卸载一个HOOK,该参数是SetWindowsHookEx()的返回值

LRESULTCallNextHookEx(

HHOOKhhk,

intnCode,

WPARAMwParam,

LPARAMlParam

);

此处的nCode要求我们填写用于传输下一个HOOK子例程的代码。如果是HC_ACTION辛运28 ,则wParam和lParam包含消息信息。如果是HC_NOREMOVE,则wParam和lParam包含消息信息,并且该消息无法从消息队列中移出。除了

LRESULTCALLBACKKeyboardProc(

intcode

WPARAMwParamhook编程

LPARAMlParam

);

这里主要是nCode参数,您需要根据此参数的值决定如何处理消息。如果nCode的值小于0,则必须返回CallNexHookEx()。 nCode可以采用HC_ACTION和HC_REMOVE这两个参数值。该系统负责编写,我们只是进行判断。有关详细用法,请参考MSDN。下面我们给出一个HOOK键盘输入的控制台示例。

五、简单程序示例

首先是我们编写的使用隐式DLL的HOOK DLL文件

//使用隐式链接提供挂钩函数SetHook()来安装全局键盘挂钩

#include

#include

#defineMYAPIextern“ C” _declspec(dllexport)//导出函数声明,应将外部“ C”放在首位

HHOOKhHook = NULL;

LRESULTCALLBACKKeyboardProc(intcode,WPARAMwParam,LPARAMlParam)

{

if(code> = 0)

return1; //该消息将不会传递到下一个HOOK子例程,也不会发送到目标窗口

其他

returnCallNextHookEx(hHook,HC_ACTION,wParam,lParam);

}

MYAPIintSetHook()

{

hHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandleA(“ KeyboardHookDLL.dll”),0);

if(hHook == NULL)

{

printf(“ SetWindowsHookEx()错误:%d \ n”,GetLastError());

return-1;

}

return0;

}

MYAPIintStopHook()

{

if(UnhookWindowsHookEx(hHook)== FALSE)

{

printf(“ UnhookWindowsHookEx()错误:%d \ n”);

return-1;

}

return0;

}

MicrosoftInternetExplorer402DocumentNotSpecified 7. 8Normal0

接下来是控制台程序,负责安装/卸载HOOK:

//一个负责安装和卸载键盘挂钩的控制台程序

#include

#include

//链接指定的库文件

#pragmacomment(lib,“ KeyboardHookDLL.lib”)

//还必须在隐式DLL可执行模块中声明DLL导入功能

外部“ C” _declspec(dllimport)intSetHook();

外部“ C” _declspec(dllimport)intStopHook();

intmain(intargc,char * argv [])

{

charYesNo;

printf(“这是有关全局键盘挂钩的测试... \ n”);

printf(“安装全局键盘挂钩... \ n”);

SetHook();

printf(“是否要卸载键盘挂钩:(YorN)\ n”);

YesNo = getchar();

if(YesNo =='Y'|| YesNo =='y')

{

printf(“开始卸载挂钩... \ n \ n”);

StopHook();

printf(“该挂钩已被卸载... \ n”);

}

system(“ pause”);

return0;

}

执行测试结果:

hook编程

输入单词时,将弹出360警告,表明这时我们的HOOK.dll正在注入单词过程中。获得许可后,该单词中的所有键盘操作都将无效。有兴趣的学生可以自己尝试一下^ _ ^

hook编程

六、问题

我在运行程序时发现问题,即退出控制台程序后,将无法再使用HOOK。当然,控制台不会正常退出并且StopHook没有运行,但是HOOK为什么会失败?有必要使HOOK工作ysb体育 ,我们的HOOK驱动程序必须始终运行吗?

老王
地址:深圳市福田区国际电子商务产业园科技楼603-604
电话:0755-83586660、0755-83583158 传真:0755-81780330
邮箱:info@qbt8.com
地址:深圳市福田区国际电子商务产业园科技楼603-604
电话:0755-83174789 传真:0755-83170936
邮箱:info@qbt8.com
地址:天河区棠安路288号天盈建博汇创意园2楼2082
电话:020-82071951、020-82070761 传真:020-82071976
邮箱:info@qbt8.com
地址:重庆南岸区上海城嘉德中心二号1001
电话:023-62625616、023-62625617 传真:023-62625618
邮箱:info@qbt8.com
地址:贵阳市金阳新区国家高新技术开发区国家数字内容产业园5楼A区508
电话:0851-84114330、0851-84114080 传真:0851-84113779
邮箱:info@qbt8.com