vc++HOOK详细讲解
- 格式:doc
- 大小:42.00 KB
- 文档页数:17
hook方法的通俗解释
"hook"方法通常是指在编程中用于改变或扩展现有代码行为的
一种技术。
它通常用于软件开发中的插件或扩展机制中,允许开发
人员在不修改原始代码的情况下,通过在特定的“hook”点插入自
定义代码来改变程序的行为。
具体来说,当一个程序在特定的事件发生时会触发一个“hook”点,开发人员可以注册他们自己的函数或代码到这个“hook”点上。
这样,当该事件发生时,注册的代码就会被执行,从而改变了程序
的行为。
举个例子,假设有一个网页应用程序,当用户点击“提交”按
钮时,程序会触发一个“beforeSubmit”钩子。
开发人员可以注册
他们自己的函数到这个钩子上,用于在表单提交之前执行一些额外
的验证或处理逻辑。
这样,无需修改原始的提交按钮代码,就可以
通过“hook”方法来扩展其行为。
总的来说,"hook"方法是一种非常灵活的技术,可以帮助开发
人员在不破坏现有代码结构的情况下,对程序进行定制和扩展。
它
在软件开发中被广泛应用,能够提高代码的可维护性和可扩展性。
warframe客服范文摘要:1.VC6 Hook 简介2.VC6 Hook 传递参数的方法3.VC6 Hook 的应用实例4.总结正文:【VC6 Hook 简介】VC6 Hook 是一种在Windows 操作系统中使用的编程技术,它可以在目标程序运行过程中,拦截和修改程序的函数调用。
这种技术可以让程序员在不修改原始代码的情况下,对程序进行功能扩展或者修复漏洞。
VC6 Hook 通常用于病毒木马开发、游戏外挂制作、软件破解等领域。
【VC6 Hook 传递参数的方法】VC6 Hook 通过修改目标程序的导入表(Import Table)来实现函数调用的拦截和修改。
具体来说,首先需要找到目标函数在导入表中的地址,然后用自己的函数体替换目标函数体。
在这个过程中,VC6 Hook 需要传递一些参数给新的函数体,以保证函数能够正常运行。
这些参数主要包括:1.目标函数的原始地址:这个地址是VC6 Hook 用来恢复原始函数调用的关键。
在拦截目标函数时,VC6 Hook 会将这个地址保存下来,以便在需要时恢复原始函数的调用。
2.目标函数的参数:在拦截目标函数时,VC6 Hook 需要将目标函数的参数传递给自己的函数体。
这些参数可以用来修改目标函数的行为,或者传递给其他函数进行进一步处理。
3.VC6 Hook 函数的返回值:当VC6 Hook 函数执行完毕后,它需要将返回值传递给目标函数调用者。
这个返回值可以是原始函数的返回值,也可以是VC6 Hook 函数处理后的结果。
【VC6 Hook 的应用实例】以一个简单的例子来说明VC6 Hook 的传递参数过程。
假设我们有一个目标函数`func`,它接受一个整数参数`a`,并返回`a`的平方。
我们可以使用VC6 Hook 技术来实现对这个函数的修改,让它返回`a`的立方。
首先,我们需要编写一个VC6 Hook 函数体,用于计算`a`的立方。
然后,在拦截目标函数时,将`a`的值传递给VC6 Hook 函数体,并将返回值传递给目标函数调用者。
c++ hook 方法在C++中,钩子(Hook)通常指的是一种在运行时改变程序行为的技术。
这通常涉及到对某个函数或某个特定事件的拦截,以便在发生某些操作时插入自定义的代码。
C++中实现钩子的方法有很多,这里我提供一个简单的例子,使用C++中的函数指针和单例模式来实现一个简单的钩子系统。
首先,定义一个函数指针类型:```cpptypedef void (*HookFunc)();```然后,定义一个钩子管理器类,它维护一个函数指针的列表:```cppclass HookManager {public:static HookManager& getInstance() {static HookManager instance; // 线程安全的单例实现return instance;}void registerHook(HookFunc func) {funcs.push_back(func);}void callHooks() {for (auto func : funcs) {func();}}private:HookManager() {}~HookManager() {} // 不允许复制和赋值std::vector<HookFunc> funcs;};```接下来,你可以在程序中注册钩子函数:```cppvoid myHookFunc1() {// 自定义代码1...}void myHookFunc2() {// 自定义代码2...}int main() {HookManager::getInstance().registerHook(myHookFunc1);HookManager::getInstance().registerHook(myHookFunc2);// ... 其他代码...HookManager::getInstance().callHooks(); // 调用所有注册的钩子函数return 0;}```上面的例子展示了一个简单的钩子系统。
系统钩子和DLL钩子的本质是一段用以处理系统消息的程序,通过系统调用,将其挂入系统。
钩子的种类有很多,每种钩子可以截获并处理相应的消息,每当特定的消息发出,在到达目的窗口之前,钩子程序先行截获该消息、得到对此消息的控制权。
此时在钩子函数中就可以对截获的消息进行加工处理,甚至可以强制结束消息的传递。
在本程序中我们需要捕获在任意窗口上的键盘输入,这就需要采用全局钩子以便拦截整个系统的消息,而全局钩子函数必须以DLL(动态连接库)为载体进行封装,VC6中有三种形式的MFC DLL可供选择,即Regular statically linked to MFC DLL(标准静态链接MFC DLL)、Regular using the shared MFC DLL(标准动态链接MFC DLL)以及Extension MFC DLL(扩展MFC DLL)。
在本程序中为方便起见采用了标准静态连接MFC DLL。
键盘钩子程序示例本示例程序用到全局钩子函数,程序分两部分:可执行程序KeyKook和动态连接库LaunchDLL。
首先创建一个MFC AppWizard(DLL)工程,并选择Regular statically linked to MFC DLL (标准静态链接MFC DLL)选项,以建立MFC扩展动态连接库LaunchDLL.dll。
之后,在相应的头文件中添加宏定义和待导出函数的声明:#define DllExport __declspec(dllexport)……DllExport void WINAPI InstallLaunchEv();……class CLaunchDLLApp : public CWinApp{public:CLaunchDLLApp();//{{AFX_VIRTUAL(CLaunchDLLApp)//}}AFX_VIRTUAL//{{AFX_MSG(CLaunchDLLApp)// NOTE - the ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code !//}}AFX_MSGDECLARE_MESSAGE_MAP()};同时在实现文件中添加全局变量Hook和全局函数LauncherHook()、SaveLog():HHOOK Hook;LRESULT CALLBACK LauncherHook(int nCode,WPARAM wParam,LPARAM lParam);void SaveLog(char* c);最后,完成以上提到的这几个函数的具体编码实现:CLaunchDLLApp theApp;……DllExport void WINAPI InstallLaunchEv(){Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)LauncherHook,theApp.m_hInst ance,0);}在此我们实现了Windows的系统钩子的安装,首先要调用SDK中的API函数SetWindowsHookEx()来安装这个钩子函数,其原型是:HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);其中,第一个参数指定钩子的类型,常用的有WH_MOUSE、WH_KEYBOARD、WH_GETMESSAGE等,在此我们只关心键盘操作所以设定为WH_KEYBOARD;第二个参数标识钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数,即当不管系统的哪个窗口有键盘输入马上会引起LauncherHook的动作;第三个参数是钩子函数所在模块的句柄,我们可以很简单的设定其为本应用程序的实例句柄;最后一个参数是钩子相关函数的ID用以指定想让钩子去钩哪个线程,为0时则拦截整个系统的消息,在本程序中钩子需要为全局钩子,故设定为0。
一、引言在C++编程中,hook是指截获并改变程序执行流程的技术。
而可变参数函数则是指参数个数不固定的函数。
结合这两个概念,我们可以实现对可变参数函数的hook,从而实现对函数行为的控制和修改。
二、可变参数函数的基本概念可变参数函数是指在函数声明中使用省略号"..."来表示函数参数个数不固定,例如printf函数就是一个典型的可变参数函数。
在C++中,可变参数函数通常使用stdarg.h头文件中的宏和函数来处理可变参数。
具体的用法是在函数中使用va_list、va_start、va_arg和va_end等宏和函数来依次访问每个可变参数。
三、C++中的函数hook函数hook是一种在程序运行时修改函数原始行为的技术。
在C++中,可以使用函数指针、动态信息库、代码注入等手段来实现函数hook。
通过hook技术,我们可以在函数执行前后添加额外的逻辑,甚至可以完全替换原始函数的实现。
这对于调试、监控、性能分析等需求非常有用。
四、可变参数函数的hook实现在C++中,可变参数函数的hook实现相对复杂一些,因为可变参数的传递和处理需要特殊的方法。
以下是一种基于函数指针和动态信息库的可变参数函数hook实现方法:1. 定义一个原始函数指针和一个替代函数指针:```c++typedef int (*OriginalFuncPtr)(const char* format, ...); OriginalFuncPtr originalFunc = nullptr;int replaceFunc(const char* format, ...);```2. 在动态信息库中实现原始函数和替代函数:```c++int originalFuncImpl(const char* format, ...) {va_list args;va_start(args, format);// 原始函数的实现int result = vprintf(format, args);va_end(args);return result;}int replaceFuncImpl(const char* format, ...) {va_list args;va_start(args, format);// 替代函数的实现int result = vfprintf(stdout, format, args);va_end(args);return result;}```3. 在程序运行时,通过动态信息库加载原始函数和替代函数:```c++void loadLibrary() {// 加载动态信息库void* handle = dlopen("libhook.so", RTLD_LAZY);if (handle) {originalFunc = (OriginalFuncPtr)dlsym(handle, "originalFuncImpl");replaceFunc = (ReplaceFuncPtr)dlsym(handle, "replaceFuncImpl");}}```4. 实现函数hook:```c++int main() {loadLibrary();// 使用原始函数originalFunc("hello, %s\n", "world");// 替换原始函数originalFunc = replaceFunc;originalFunc("hello, %s\n", "world");// 卸载动态信息库dlclose(handle);return 0;}```五、总结通过上述实现,我们成功地对可变参数函数进行了hook,实现了对函数行为的修改和控制。
hook实现原理Hook,即钩子,是一种在特定事件发生之前、之中或之后执行的代码。
在编程中,钩子技术被广泛应用于各种场景,如进程间通信、事件处理、性能监控等。
本文将介绍钩子的基本原理,以及在C++编程语言中使用钩子进行事件处理的实现方法。
一、钩子的基本原理钩子是一种特殊的函数,通常在特定事件发生时被系统调用。
钩子的实现原理通常是在系统调用事件发生之前,通过某种方式拦截事件的执行流程,并添加自定义的代码。
这种实现方式依赖于编程语言的底层机制,通常涉及到操作系统的内存管理、进程控制、中断处理等方面。
在C++中,钩子的实现通常需要借助操作系统提供的API函数或内核对象来实现。
钩子的注册和注销通常需要调用相应的API函数,以便在特定事件发生时触发钩子函数。
同时,钩子函数需要具备可移植性,以便在不同的操作系统和平台上使用。
1. 钩子注册和注销在C++中,钩子的注册和注销通常需要使用操作系统提供的API函数。
例如,在Windows操作系统中,可以使用SetWindowsHookEx()函数注册钩子,使用UnhookWindowsHookEx()函数注销钩子。
这些函数需要传递钩子函数的地址作为参数,以便在特定事件发生时执行钩子函数。
2. 钩子函数的执行当事件发生时,操作系统会根据注册的钩子函数列表,依次调用相应的钩子函数。
每个钩子函数会在事件发生的过程中添加自定义的代码,从而实现钩子的功能。
钩子函数的执行顺序和执行时机取决于注册时的顺序和条件。
3. 钩子的类型和用途钩子根据实现方式可以分为不同的类型,如键盘钩子、鼠标钩子、定时器钩子等。
不同类型的钩子适用于不同的场景,如键盘钩子可用于实现键盘快捷键功能,鼠标钩子可用于实现鼠标事件处理等。
根据用途不同,钩子可以应用于各种编程场景,如游戏开发、网络通信、应用性能监控等。
三、案例分析:C++游戏开发中的钩子实现在C++游戏开发中,钩子技术常用于事件处理和性能监控。
以下是一个简单的示例程序,展示了如何在游戏开发中使用钩子技术:1. 程序初始化时注册鼠标移动钩子在程序初始化时,使用系统API函数注册鼠标移动钩子。
C#Hook前⾔ 在说C# Hook之前,我们先来说说什么是Hook技术。
相信⼤家都接触过外挂,不管是修改游戏客户端的也好,盗取密码的也罢,它们都是如何实现的呢? 实际上,Windows平台是基于事件驱动机制的,整个系统都是通过消息的传递来实现的。
当进程有响应时(包括响应⿏标和键盘事件),则Windows会向应⽤程序发送⼀个消息给应⽤程序的消息队列,应⽤程序进⽽从消息队列中取出消息并发送给相应窗⼝进⾏处理。
⽽Hook则是Windows消息处理机制的⼀个平台,应⽤程序可以在上⾯设置⼦程以监视指定窗⼝的某种消息,⽽且所监视的窗⼝可以是其他进程所创建的。
当消息到达后,在⽬标窗⼝处理函数之前处理它。
钩⼦机制允许应⽤程序截获处理window消息或特定事件。
所以Hook就可以实现在键盘/⿏标响应后,窗⼝处理消息之前,就对此消息进⾏处理,⽐如监听键盘输⼊,⿏标点击坐标等等。
某些盗号⽊马就是Hook了指定的进程,从⽽监听键盘输⼊了什么内容,进⽽盗取账户密码。
C# Hook 我们知道C#是运⾏在.NET平台之上,⽽且是基于CLR动态运⾏的,所以只能操作封装好的函数,且⽆法直接操作内存数据。
⽽且在C#常⽤的功能中,并未封装Hook相关的类与⽅法,所以如果⽤C#实现Hook,必须采⽤调⽤WindowsAPI的⽅式进⾏实现。
WindowsAPI函数属于⾮托管类型的函数,我们在调⽤时必须遵循以下⼏步: 1、查找包含调⽤函数的DLL,如User32.dll,Kernel32.dll等。
2、将该DLL加载到内存中,并注明⼊⼝ 3、将所需参数转化为C#存在的类型,如指针对应Intptr,句柄对应int类型等等 4、调⽤函数 我们本篇需要使⽤的函数有以下⼏个: SetWindowsHookEx ⽤于安装钩⼦ UnhookWindowsHookEx ⽤于卸载钩⼦ CallNextHookEx 执⾏下⼀个钩⼦ 详细API介绍请参考MSDN官⽅声明 接下来在C#中需要⾸先声明此API函数:[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,IntPtr hInstance, int threadId);[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]public static extern bool UnhookWindowsHookEx(int idHook);[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]public static extern int CallNextHookEx(int idHook, int nCode,IntPtr wParam, IntPtr lParam); 声明后即可实现调⽤,SetWindowsHookEx()把⼀个应⽤程序定义的钩⼦⼦程安装到钩⼦链表中,SetWindowsHookEx函数总是在Hook链的开头安装Hook⼦程。
一、声明Windows API 中的函数和常量//键盘Hook结构函数[StructLayout(LayoutKind.Sequential)]public class KeyBoardHookStruct{public int vkCode;public int scanCode;public int flags;public int time;public int dwExtraInfo;}#region DllImport//设置钩子[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]//抽掉钩子public static extern bool UnhookWindowsHookEx(int idHook);[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]//调用下一个钩子public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);//取得模块句柄[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]private static extern IntPtr GetModuleHandle(string lpModuleName);//寻找目标进程窗口[DllImport("USER32.DLL")]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);//设置进程窗口到最前[DllImport("USER32.DLL")]public static extern bool SetForegroundWindow(IntPtr hWnd);//模拟键盘事件[DllImport("User32.dll")]public static extern void keybd_event(Byte bVk, Byte bScan, Int32 dwFlags, Int32 dwExtraInfo);//释放按键的常量private const int KEYEVENTF_KEYUP =2;本例所使用的函数比较少,它们都在系统的USER32.dll里,包括:设置和取消钩子、调用下一个钩子、导入进程、模拟键盘等等。
本文将试图以下面的顺序讲解HOOK的大部分内容:1、 WINDOWS的消息机制2、 HOOK介绍3、 HOOK链4、 HOOK钩子的作用范围5、 HOOK类型6、回调函数7、 HOOK钩子的安装与卸载8、 HOOK实例演示+++++++++++++++++++WINDOWS的消息机制+++++++++++++++++++Windows系统是以消息处理为其控制机制,系统通过消息为窗口过程(windowsprocedure)传递输入。
系统和应用两者都可以产生消息。
对于每个输入事件,例如用户按下了键盘上的某个键、移动了鼠标、单击了一个控件上的滚动条,等等,系统都将产生一系列消息。
此外,对于应用带给系统的变化,如字体资源的改变、应用本身窗口的改变,系统都将通过消息以响应这种变化。
应用通过产生消息指示应用的窗口完成特定的任务,或与其他应用的窗口进行通信。
每个窗口都有一个处理Windows系统发送消息的处理程序,称为窗口程序。
它是隐含在窗口背后的一段程序脚本,其中包含对事件进行处理的代码。
Windows系统为每条消息指定了一个消息编号,例如当一个窗口变为活动窗口时,它事实上是收到一条来自Windows系统的WM_ACTIVATE消息,该消息的编号为6,它对应于VB窗口的Activate事件。
对于窗口来说,诸如Open、Activate、MouseDown、Resize等事件,实际上对应的是窗口内部的消息处理程序,这些程序对于用户来讲是不可见的。
类似地,命令按钮也有消息处理程序,它的处理程序响应诸如WM_LBUTTONDOWN和WM_RBUTTONDOWN之类的消息,即激活命令按钮的MouseDown事件.WINDOWS的消息处理机制为了能在应用程序中监控系统的各种事件消息,提供了挂接各种回调函数(HOOK)的功能.这种挂钩函数(HOOK)类似扩充中断驱动程序,挂钩上可以挂接多个反调函数构成一个挂接函数链.系统产生的各种消息首先被送到各种挂接函数,挂接函数根据各自的功能对消息进行监视、修改和控制等,然后交还控制权或将消息传递给下一个挂接函数以致最终达到窗口函数。
vc++HOOK详细讲解消息钩子函数入门Windows 系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。
而钩子是Windows 系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。
钩子可以监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。
这样,我们就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。
可见,利用钩子可以实现许多特殊而有用的功能。
因此,对于高级编程人员来说,掌握钩子的编程方法是很有必要的。
钩子的类型一.按事件分类,有如下的几种常用类型(1)键盘钩子和低级键盘钩子可以监视各种键盘消息。
(2)鼠标钩子和低级鼠标钩子可以监视各种鼠标消息。
(3)外壳钩子可以监视各种Shell 事件消息。
比如启动和关闭应用程序。
(4)日志钩子可以记录从系统消息队列中取出的各种事件消息。
(5)窗口过程钩子监视所有从系统消息队列发往目标窗口的消息。
此外,还有一些特定事件的钩子提供给我们使用,不一一列举。
下面描述常用的Hook 类型:1、WH_CALLWNDPROC 和WH_CALLWNDPROCRET Hooks WH_CALLWNDPROC 和WH_CALLWNDPROCRET Hooks 使你可以监视发送到窗口过程的消息。
系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook 子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPRO CRET Hook 子程。
WH_CALLWNDPROCRET Hook 传递指针到CWPRETSTRUCT 结构,再传递到Hook 子程。
CWPRETSTRUCT 结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。
2、WH_CBT Hook在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括:1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;2. 完成系统指令;3. 来自系统消息队列中的移动鼠标,键盘事件;4. 设置输入焦点事件;5. 同步系统消息队列事件。
Hook 子程的返回值确定系统是否允许或者防止这些操作中的一个。
3、WH_DEBUG Hook在系统调用系统中与其他Hook 关联的Hook 子程之前,系统会调用WH_DEBUG Hook 子程。
你可以使用这个Hook 来决定是否允许系统调用与其他Hook 关联的Hook 子程。
4、WH_FOREGROUNDIDLE Hook当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook 执行低优先级的任务。
当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook 子程。
5、WH_GETMESSAGE Hook应用程序使用WH_GETMESSAGE Hook 来监视从GetMessage or PeekMessage 函数返回的消息。
你可以使用WH_GETMESSAGE Hook 去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。
6、WH_JOURNALPLAYBACK HookWH_JOURNALPLAYBACK Hook 使应用程序可以插入消息到系统消息队列。
可以使用这个Hook 回放通过使用WH_JOURNALRECORD Hook 记录下来的连续的鼠标和键盘事件。
只要WH_JOURNALPLAYBACK Hook 已经安装,正常的鼠标和键盘事件就是无效的。
WH_JOURNALPLAYBACK Hook 是全局Hook,它不能象线程特定Hook 一样使用。
WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处理来自回放Hook 当前消息之前需要等待多长时间(毫秒)。
这就使Hook 可以控制实时事件的回放。
WH_JOURNALPLAYBACK 是system-wide local hooks,它們不會被注射到任何行程位址空間。
(估计按键精灵是用这个hook 做的)7、WH_JOURNALRECORD HookWH_JOURNALRECORD Hook 用来监视和记录输入事件。
典型的,可以使用这个Hook 记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook 来回放。
WH_JOURNALRECORD Hook 是全局Hook,它不能象线程特定Hook 一样使用。
WH_JOURNALRECORD 是system-wide local hooks,它們不會被注射到任何行程位址空間。
8、WH_KEYBOARD Hook在应用程序中,WH_KEYBOARD Hook 用来监视WM_KEYDOWN and WM_KEYUP 消息,这些消息通过GetMessage or PeekMessage function 返回。
可以使用这个Hook 来监视输入到消息队列中的键盘消息。
9、WH_KEYBOARD_LL HookWH_KEYBOARD_LL Hook 监视输入到线程消息队列中的键盘消息。
10、WH_MOUSE HookWH_MOUSE Hook 监视从GetMessage 或者PeekMessage 函数返回的鼠标消息。
使用这个Hook 监视输入到消息队列中的鼠标消息。
11、WH_MOUSE_LL HookWH_MOUSE_LL Hook 监视输入到线程消息队列中的鼠标消息。
12、WH_MSGFILTER 和WH_SYSMSGFILTER Hooks WH_MSGFILTER 和WH_SYSMSGFILTER Hooks 使我们可以监视菜单,滚动条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。
WH_MSGFILTER Hook 只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook 子程的应用程序建立的对话框的消息。
WH_SYSMSGFILTER Hook 监视所有应用程序消息。
WH_MSGFILTER 和WH_SYSMSGFILTER Hooks 使我们可以在模式循环期间过滤消息,这等价于在主消息循环中过滤消息。
通过调用CallMsgFilter function 可以直接的调用WH_MSGFILTER Hook。
通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循环里一样。
13、WH_SHELL Hook外壳应用程序可以使用WH_SHELL Hook 去接收重要的通知。
当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook 子程。
WH_SHELL 共有5钟情況:1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁;2. 当Taskbar 需要重画某个按钮;3. 当系统需要显示关于Taskbar 的一个程序的最小化形式;4. 当目前的键盘布局状态改变;5. 当使用者按Ctrl+Esc 去执行Task Manager (或相同级别的程序)。
按照惯例,外壳应用程序都不接收WH_SHELL 消息。
所以,在应用程序能够接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function 注册它自己。
以上是13 种常用的hook 类型!二.按使用范围分类,主要有线程钩子和系统钩子(1)线程钩子监视指定线程的事件消息。
(2)系统钩子监视系统中的所有线程的事件消息。
因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL) 中。
这是系统钩子和线程钩子很大的不同之处。
几点需要说明的地方:(1)如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。
(2)对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。
当前钩子处理结束后应把钩子信息传递给下一个钩子函数。
而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
(3)钩子特别是系统钩子会消耗消息处理时间,降低系统性能。
只有在必要的时候才安装钩子,在使用完毕后要及时卸载。
编写钩子程序编写钩子程序的步骤分为三步:定义钩子函数、安装钩子和卸载钩子。
1.定义钩子函数钩子函数是一种特殊的回调函数。
钩子监视的特定事件发生后,系统会调用钩子函数进行处理。
不同事件的钩子函数的形式是各不相同的。
下面以鼠标钩子函数举例说明钩子函数的原型:LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)参数wParam 和lParam 包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。
nCode包含有关消息本身的信息,比如是否从消息队列中移出。
我们先在钩子函数中实现自定义的功能,然后调用函数CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。
CallNextHookEx.的原型如下:LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam ) 参数hhk 是钩子句柄。
nCode、wParam 和lParam 是钩子函数。
当然也可以通过直接返回TRUE 来丢弃该消息,就阻止了该消息的传递。
2.安装钩子在程序初始化的时候,调用函数SetWindowsHookEx 安装钩子。
其函数原型为:HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId ) 参数idHook 表示钩子类型,它是和钩子函数类型一一对应的。
比如,WH_KEYBOARD 表示安装的是键盘钩子,WH_MOUSE 表示是鼠标钩子等等。
Lpfn 是钩子函数的地址。
HMod 是钩子函数所在的实例的句柄。
对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL 句柄。
dwThreadId 指定钩子所监视的线程的线程号。
对于全局钩子,该参数为NULL。
SetWindowsHookEx 返回所安装的钩子句柄。
3.卸载钩子当不再使用钩子时,必须及时卸载。
简单地调用函数BOOL UnhookWindowsHookEx(HHOOK hhk)即可。
值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。
线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。