Windows 钩子

news/2024/7/3 20:35:09 标签: windows, basic, dll, hook, keyboard, 任务

Windows钩子

Windows应用程序的运行模式是基于消息驱动的,任何线程只要注册了窗口类都会有一个消息队列来接受用户的消息和系统消息。为了取得特定线程接受或发送的消息,就要用到windows提供的钩子。

1、钩子的概念

钩子(Hook),Windows消息处理机制中的一个监视点,应用程序可以在这里安装一个子程序(钩子函数)一监视制定窗口某种类型的消息,所监视的窗口可以是其他进程创建的。当消息到达后,在没有到达目标窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数既可以加工处理(改变)该消息,也可以不作处理而继续传递该消息。

总之,关于Windows钩子要知道以下几点:

(1)钩子是用来截获系统中的消息流的。利用钩子可以处理任何感兴趣的消息,包括其他进程的消息。

(2)截获消息后,用于处理消息的子程序叫做钩子函数,它是应用程序自定义的一个函数,在安装钩子时要把这个函数的地址告诉Windows

(3)系统中同一时间可能有多个进程安装了钩子函数,多个钩子函数在一起组成钩子链。所以在处理截获到的消息时,应该把消息事件传递下去,以便其他钩子也有机会处理这一消息。

钩子会是系统变慢,因为它增加了系统对每个消息的处理量。仅应该在必要的时候才安装钩子,而且在不需要的时候应尽快移除。

2、钩子的安装和卸载

1、安装钩子

SetWindowsHookEx 函数可以把用应用程序定义的钩子函数安装到系统中。函数用法如下:

HHOOK SetWindowsHookEx(         

int idHook, //制定钩子的类型

HOOKPROC lpfn, //钩子函数的地址。如果使用的是远程钩子,钩子函数必须放在一个DLL

HINSTANCE hMod, //钩子函数所在DLL的实例句柄。如果是一个局部的钩子,该参数的值为NULL

DWORD dwThreadId //制定要为哪个线程安装钩子。如果该值为0,那么该钩子将被解释成系统范围内的

);

参数解释:

(1)idHook参数制定了要安装的钩子类型,可以是下列取值之一:

WH_CALLWNDPROC:当目标线程调用SendMessage函数发送消息时,钩子函数被调用 

WH_CALLWNDPROCRET:SendMessage发送的消息返回时,钩子函数被调用

WH_GETMESSAGE:当目标线程调用GetMessagePeekMessage

WM_KEYBOARD:当从消息队列中查询WM_KEYUPWM_KEYDOWN消息时

WH_MOUSE:当调用从消息队列中查询鼠标事件时

WH_MSGFILTER:当对话框、菜单或滚动条要处理一个消息时,钩子函数被调用。该钩子时局部的,它是为那些有自己消息处理过程的控件设计的

WH_SYSMSGFILTER:WH_MSGFILTER一样,只不过是系统范围的

WH_JOURNALRECORD:Windows从硬件队列中获得消息时

WH_JOURNALPLAYBACK:当一个事件从系统的硬件输入队列中被请求时

WH_SHELL:当关于Windows外壳事件发生时,比如任务条需要重画它的按钮

WH_CBT:当基于计算机的训练(CBT)事件发生时

WH_FOREGROUNDIDLE:Windows自己使用,一般的应用程序很少使用

WH_DEBUG:用来给钩子函数除错

(2)lpfn参数是钩子函数的地址。钩子安装以后如果有相应的消息发生,Windows将调用此参数指定的函数。比如,idHook的值时WH_MOUSE,则当目标线程的消息队列中有鼠标消息取出时,lpfn函数就会被调用。

如果dwThreadId参数是0,或者指定一个由其他进程创建的线程IDlpfn参数指向的钩子函数必须位于一个DLL中。这是因为进程的地址空间相互隔离的,发生事件的进程不能调用其他进程地址空间的钩子函数。如果钩子函数的实现代码在DLL中,在相关事件发生时,系统会把这个DLL插入到发生事件的进程的地址空间,使它能够调用钩子函数。这种需要将钩子函数写入DLL以便挂钩其他进程事件的钩子称为远程钩子。

如果dwThreadID参数指定一个由自身进程创建的线程IDlpfn参数指向的钩子函数只要在当前进程中即可,不必写入DLL。这种仅挂钩属于自身进程事件的钩子称为局部钩子。

(3)hmod参数是钩子函数所在的DLL的实例句柄,如果钩子函数不在DLL中,应将hmod的值设为NULL

(4)dwThreadID参数指定要与钩子相关联的线程ID号。如果设为0,那么该钩子就是系统范围内的,即钩子函数将关联到系统内的所有线程。

2、钩子函数

钩子安装以后如果有相应的消息发生,Windows将调用SetWindowsHookEx函数指定的钩子函数lpfn。钩子函数的一般形式如下所示:

LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)

{

//...处理该消息的代码

return ::CallNextHookEx(hHook,nCode,wParam,lParam);

}

HookProc是应用程序定义的名字。nCode参数是Hook代码,钩子函数使用这个参数来确定任务,它的值依赖于Hook的类型。wParamlParam参数的值依赖于Hook代码,但是它的典型的值时一些关于发送或者接受消息的信息。

因为系统中可能会有多个钩子存在,所以要调用CallNextHookEx函数把消息传到链中下一个钩子。hHook参数是安装钩子时得到的钩子句柄(SetWindowsHookEx的返回值)

3、卸载钩子

要卸载钩子,可以调用 UnHookWindowsHookEx函数。

BOOL UnhookWindowsHookEx(HHOOK hhk); // hhk为要卸载的钩子函数

示例可在我的资源中找到。

1、通过内存地址取得模块句柄

HMODULE WINAPI ModuleFromAddress(PVOID pv) 

{

MEMORY_BASIC_INFORMATION mbi;

if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)

{

return (HMODULE)mbi.AllocationBase;

}

else

{

return NULL;

}

}

MEMORY_BASIC_INFORMATION结构体:

typedef struct _MEMORY_BASIC_INFORMATION { 

  PVOID BaseAddress;  //保留区域的基地址

  PVOID AllocationBase;  //VirtualAlloc函数分配的基地址

  DWORD AllocationProtect;  //初次保留时设置的保护属性,可能是PAGE_EXECUTE,PAGE_READWRITE

  DWORD RegionSize;  //区域大小

  DWORD State;  //状态(提交、保留或空闲)

  DWORD Protect;  //当前访问保护属性

  DWORD Type;  //页面类型

  } MEMORY_BASIC_INFORMATION; 

typedef MEMORY_BASIC_INFORMATION *PMEMORY_BASIC_INFORMATION; 

虚拟管理内存函数VirtualQuery:

DWORD VirtualQuery(

  LPCVOID lpAddress, //内存地址

  PMEMORY_BASIC_INFORMATION lpBuffer, // MEMORY_BASIC_INFORMATION 指针

  DWORD dwLength //MEMORY_BASIC_INFORMATION对象的大小

); 

 

摘自:王艳平 张铮《windows程序设计<第二版>》其中示例也此书中提供的光盘。


http://www.niftyadmin.cn/n/1713881.html

相关文章

Windos 程序的生与死

Windows程序的生与死 ------摘自侯俊杰《深入浅出MFC》 1、 程序的初始化过程中调用CreateWindow&#xff0c;为程序建立了一个窗口&#xff0c;作为程序的屏幕舞台&#xff0c;CreateWindow产生窗口之后会送出WM_CREATE直接给窗口函数&#xff0c;后者于是可以在此时做一些初…

“cannot access the ClassView information file, ClassView information will not be available.”的解决办法

解决步骤&#xff1a; 1.关闭工程2.删除工程下.clw .ncb 文件及/debug目录&#xff0c;3.重建工程build all 具体解释如下&#xff1a; dsp 工程文件&#xff0c;文本格式&#xff0c;不可丢失或损坏 .dsw 工作区文件&#xff0c;丢失或损坏时&#xff0c;可点击.dsp文件打…

我是一个平庸的程序员

很喜欢这些话&#xff1a;“我是一个平庸的程序员&#xff0c;我只知道最简单的命令语法&#xff0c;但懂得在哪能够找到更复杂的命令语法&#xff0c;不知道如何编写最高效的代码&#xff0c;但懂得在必要时如何重写和测试比较高效的代码。我可以克服重重困难独辟蹊径达到目标…

我很忙

最近真的太忙了&#xff0c;很多事情都一起来了&#xff0c;让人有点乱&#xff0c;但我必须要把这些事情做好&#xff0c;先静下心来&#xff0c;慢慢想&#xff0c;好好做&#xff01;

C++虚函数表解析(转) ——写的真不错,忍不住转了

C中的虚函数的作用主要是实现了多态的机制。关于多态&#xff0c;简而言之就是用父类型别的指针指向其子类的实例&#xff0c;然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”&#xff0c;这是一种泛型技术。所谓泛型技术&#xff0c;说白了…

嗨!我爱世界杯

昨天的网很不好&#xff0c;打不开网页&#xff0c;更别提看球赛了&#xff0c;到11点&#xff0c;断网了&#xff0c;5号楼的人疯了&#xff0c;向楼下丢玻璃瓶&#xff0c;甚至暖瓶&#xff0c;强烈要求开网看世界杯&#xff0c;经过大约半个小时的闹腾&#xff0c;学校开网了…

一种体会

现在我不想写什么技术&#xff0c;只想记录下最近的心情&#xff0c;我在做一个ip管理系统&#xff0c;相当于一个ip管理小工具&#xff0c;离放假的日子越来越近了&#xff0c;我的进度却很慢&#xff0c;端午节的三天假期&#xff0c;我都在做有关ip本身字段的问题&#xff0…

还没来得及。。。

这些天太热了&#xff0c;晚上在宿舍几乎不能睡着&#xff0c;每次暑假前都是这样的。也就意味着大三下学期就要结束了&#xff0c;马上就是大四了&#xff0c;会有很多事情等着我们去处理&#xff0c;一学期快结束了&#xff0c;本来是应该先休息几天&#xff0c;松口气的&…