论文部分内容阅读
摘要:钩子技术利用Windows的消息传递机制,将钩子处理程序挂接在操作系统的消息处理列表中,从而截获操作系统传递给其他应用程序的消息。钩子处理程序得到消息并作出处理后还可以让该消息继续传递下去。利用钩子技术监控台球游戏的键盘和鼠标消息,使游戏者取得了较好的成绩。
关键字:钩子;回调函数;消息
1 引言
Windows程序使用消息传递机制,所有的程序都通过消息来驱动。应用程序运行的时候会产生和得到各种消息,一般情况下操作系统会把消息传递给合法的消息使用者。但是采用钩子程序技术可以截获操作系统发给正常程序的消息。操作系统通过系统调用,把钩子程序载入系统。应用程序运行时,当特定的消息发出之后,在消息送到目标应用程序之前,钩子程序就先截获这个消息,并且可以根据该消息的内容做出处理和动作,处理消息之后还可以把消息交还给系统继续传递该消息,也可以强制结束该消息的传递[1]。
钩子函数是一种特殊的回调函数,钩子函数有一个与之相关联的钩子链表,该链表由系统来管理。钩子函数由钩子的使用者编写,用以对钩子所截获的消息加以处理从而实现钩子使用者的意图。当钩子所关注的各类消息发生时,操作系统就先把消息传给钩子程序。
最常用的钩子程序有键盘钩子和鼠标钩子。分别可以监视各种键盘消息和各种鼠标消息。此外比较常用的还有外壳钩子用以监视Shell消息、窗口钩子监视送往目口的消息等[2]。
使用钩子程序的流程一般是先安装钩子,将钩子程序挂接到操作系统所维护的钩子列表上,当消息发生时由钩子处理程序(回调函数)执行消息处理动作,最后钩子使用完毕后可以卸载钩子。
2 钩子程序获取鼠标和键盘消息
电脑台球游戏依靠鼠标和键盘去模拟台球杆的各种动作,台球发生碰撞后球前进的方向取决于游戏鼠标的状态和碰撞点等信息,这些只能靠玩家凭经验估测,不甚准确。利用钩子程序可以获取台球球心鼠标位置,便能利用基本的几何和碰撞原理计算出台球碰撞后的前进方向,从而使台球正确地进入洞口,提高游戏成绩。
台球钩子程序需要使用的钩子类型是鼠标钩子和键盘钩子。
2.1 声明与钩子相关的函数
安装Win32钩子,要调用操作系统的API函数SetWindowsHookEx,其在C#下的原型是:
int SetWindowsHookEx(int idHook,HookProc lpfn,IntPtr hInstance,int threadId);
其中第一个参数idHook表示钩子类型。 第二个参数Lpfn是钩子函数的入口地址。第三个参数hInstance是钩子函数所在的实例的句柄。第四个参数dwThreadId是钩子所监控的线程号。全局钩子的该参数为NULL。钩子函数在处理完消息后可以再调用另外一个API函数CallNextHookEx()来继续传递它。
本文实验使用.net平台下的C#语言编写,所需调用的鼠标和键盘钩子函数位于user32.dll文件中,调用需声明:
[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 int SetWindowsHookEx(int idHook,KeyboardProc lpfn,IntPtr hInstance,int threadId);
除了安装(挂接)钩子以外,删除钩子和继续传递消息等函数也需要做类似的引用声明。
2.2 回调函数
钩子程序必须自己负责完成对消息的处理,需要编写并安装回调函数,其关键代码是:
//安装鼠標钩子
MyProcedure = new HookProc(this.MouseHookProc);
hHook = SetWindowsHookEx(WH_MOUSE_LL,MyProcedure,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
if(hHook == 0)MessageBox.Show("SetWindowsHookEx Failed");
// 安装键盘钩子
KeyboardHookProcedure = new KeyboardProc(this.KeyboardHookProc);
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardHookProcedure,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
if(hKeyboardHook == 0)MessageBox.Show("SetWindowsHookEx failed.");
上述代码中的this.MouseHookProc和this.KeyboardHookProc就是钩子处理程序(回调函数)。本文实验中这两个函数的原型是: int MouseHookProc(int nCode,IntPtr wParam,IntPtr lParam)
int KeyboardHookProc(int nCode,IntPtr wParam,IntPtr lParam)
参数wParam和lParam包含截获的消息中关于鼠标的位置、状态和键盘的按键值等信息。nCode的取值本可以决定是否该消息从消息队列中移出,本文实验中无论该参数取何值都会将消息继续传递下去。
本文实验在这两个回调函数中编写相应的鼠标和键盘事件处理过程。回调函数处理完所截获的鼠标和键盘消息后将消息继续传递下去,以使得台球游戏得到必要的数据从而继续运行下去。这一步骤只需要调用CallNextHookEx()函数就可以了。函数调用形式是:
CallNextHookEx(hHook,nCode,wParam,lParam);
2.3 卸载钩子
钩子程序使用完毕之后可以卸载,以释放其所占用的系统资源,卸载钩子使用user32.dll中的UnhookWindowsHookEx()函数:
bool ret = UnhookWindowsHookEx(hHook);
bool retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
其中的参数hHOOK和hkeyboardHook就是所挂接的回调函数句柄。
3 截获台球游戏数据
运行钩子程序,并启动台球游戏。游戏运行过程中,只要鼠标处在游戏界面以内,那么关于鼠标的消息就会被操作系统发给台球程序。但是在挂接了钩子程序之后,操作系统会将发给台球游戏的鼠标消息发给钩子处理程序,从而钩子处理程序获知了鼠标位置信息,再通过事先准备好的球体识别功能函数识别出母球和目标球球心及半径。具备这些信息后就能准确计算出两球相撞后的前进方向并画出球的前进路线。如果路线指向球洞就表明成功瞄准,玩家借以代替目测瞄准。
其中球体中心识别功能利用了键盘钩子。游戏者将鼠标移至球体中心位置附近后按下键盘上的特定键,比如“t”键。钩子程序捕获台球游戏的该按键消息之后,结合此时捕获的鼠标坐标信息,通过预先编写好的球体识别函数找到 球心准确坐标。该函数以鼠标位置为中心搜索球体边缘并计算出球心坐标,其中的几何知识与钩子技术无关,本文不做介绍。
4 效果分析
利用钩子程序辅助台球游戏投入实验之后,能实时准确地反馈台球游戏中鼠标的位置信息,也能截获键盘的按键消息。只是键盘消息中的按键值与通常的ASCII码并完全不一致,键盘上也存在一些非ASCII符号,所以在编写键盘钩子程序的时候需要查阅键盘键值表。
本文实验采用.net平台下的C#语言编写钩子程序,使用者感受到系统性能受到一定影响。分析原因可能有两个:一是钩子程序挂接在操作系统的监控链表之后给系统带来了一定的负荷[3],二是C#程序依赖于.net Framework 2.0以上的平台,而使用者所用的计算机型号较老,性能不佳,如果用C++改写此程序可能性能会更好一些。
5 结语
操纵电脑游戏获得的好处是有限的,但是钩子技术带给人的启发意义是较大的。利用钩子监控各类消息的功能,很容易理解电脑安全中的数据窃取以及相应的安全防范技术原理。这对于推进编程技术,促进电脑安全软件的发展很有意义。
参考文献:
[1]施琛.基于钩子函数的应用程序快捷键设置[j].计算机与数字工程, 2013年第1期:92-94
[2]高曉.Hook及其防御技术探析[j]. 长春工业大学学报(自然科学版), 2013年12月第34卷第6期:686-691
[3]魏东.利用日志钩子函数实现Windows系统信息的捕获[j].昆明理工大学学报, 2002 8月第27卷第4期:86-89
作者简介:秦丹,讲师,硕士,研究方向:人工智能
关键字:钩子;回调函数;消息
1 引言
Windows程序使用消息传递机制,所有的程序都通过消息来驱动。应用程序运行的时候会产生和得到各种消息,一般情况下操作系统会把消息传递给合法的消息使用者。但是采用钩子程序技术可以截获操作系统发给正常程序的消息。操作系统通过系统调用,把钩子程序载入系统。应用程序运行时,当特定的消息发出之后,在消息送到目标应用程序之前,钩子程序就先截获这个消息,并且可以根据该消息的内容做出处理和动作,处理消息之后还可以把消息交还给系统继续传递该消息,也可以强制结束该消息的传递[1]。
钩子函数是一种特殊的回调函数,钩子函数有一个与之相关联的钩子链表,该链表由系统来管理。钩子函数由钩子的使用者编写,用以对钩子所截获的消息加以处理从而实现钩子使用者的意图。当钩子所关注的各类消息发生时,操作系统就先把消息传给钩子程序。
最常用的钩子程序有键盘钩子和鼠标钩子。分别可以监视各种键盘消息和各种鼠标消息。此外比较常用的还有外壳钩子用以监视Shell消息、窗口钩子监视送往目口的消息等[2]。
使用钩子程序的流程一般是先安装钩子,将钩子程序挂接到操作系统所维护的钩子列表上,当消息发生时由钩子处理程序(回调函数)执行消息处理动作,最后钩子使用完毕后可以卸载钩子。
2 钩子程序获取鼠标和键盘消息
电脑台球游戏依靠鼠标和键盘去模拟台球杆的各种动作,台球发生碰撞后球前进的方向取决于游戏鼠标的状态和碰撞点等信息,这些只能靠玩家凭经验估测,不甚准确。利用钩子程序可以获取台球球心鼠标位置,便能利用基本的几何和碰撞原理计算出台球碰撞后的前进方向,从而使台球正确地进入洞口,提高游戏成绩。
台球钩子程序需要使用的钩子类型是鼠标钩子和键盘钩子。
2.1 声明与钩子相关的函数
安装Win32钩子,要调用操作系统的API函数SetWindowsHookEx,其在C#下的原型是:
int SetWindowsHookEx(int idHook,HookProc lpfn,IntPtr hInstance,int threadId);
其中第一个参数idHook表示钩子类型。 第二个参数Lpfn是钩子函数的入口地址。第三个参数hInstance是钩子函数所在的实例的句柄。第四个参数dwThreadId是钩子所监控的线程号。全局钩子的该参数为NULL。钩子函数在处理完消息后可以再调用另外一个API函数CallNextHookEx()来继续传递它。
本文实验使用.net平台下的C#语言编写,所需调用的鼠标和键盘钩子函数位于user32.dll文件中,调用需声明:
[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 int SetWindowsHookEx(int idHook,KeyboardProc lpfn,IntPtr hInstance,int threadId);
除了安装(挂接)钩子以外,删除钩子和继续传递消息等函数也需要做类似的引用声明。
2.2 回调函数
钩子程序必须自己负责完成对消息的处理,需要编写并安装回调函数,其关键代码是:
//安装鼠標钩子
MyProcedure = new HookProc(this.MouseHookProc);
hHook = SetWindowsHookEx(WH_MOUSE_LL,MyProcedure,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
if(hHook == 0)MessageBox.Show("SetWindowsHookEx Failed");
// 安装键盘钩子
KeyboardHookProcedure = new KeyboardProc(this.KeyboardHookProc);
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardHookProcedure,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
if(hKeyboardHook == 0)MessageBox.Show("SetWindowsHookEx failed.");
上述代码中的this.MouseHookProc和this.KeyboardHookProc就是钩子处理程序(回调函数)。本文实验中这两个函数的原型是: int MouseHookProc(int nCode,IntPtr wParam,IntPtr lParam)
int KeyboardHookProc(int nCode,IntPtr wParam,IntPtr lParam)
参数wParam和lParam包含截获的消息中关于鼠标的位置、状态和键盘的按键值等信息。nCode的取值本可以决定是否该消息从消息队列中移出,本文实验中无论该参数取何值都会将消息继续传递下去。
本文实验在这两个回调函数中编写相应的鼠标和键盘事件处理过程。回调函数处理完所截获的鼠标和键盘消息后将消息继续传递下去,以使得台球游戏得到必要的数据从而继续运行下去。这一步骤只需要调用CallNextHookEx()函数就可以了。函数调用形式是:
CallNextHookEx(hHook,nCode,wParam,lParam);
2.3 卸载钩子
钩子程序使用完毕之后可以卸载,以释放其所占用的系统资源,卸载钩子使用user32.dll中的UnhookWindowsHookEx()函数:
bool ret = UnhookWindowsHookEx(hHook);
bool retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
其中的参数hHOOK和hkeyboardHook就是所挂接的回调函数句柄。
3 截获台球游戏数据
运行钩子程序,并启动台球游戏。游戏运行过程中,只要鼠标处在游戏界面以内,那么关于鼠标的消息就会被操作系统发给台球程序。但是在挂接了钩子程序之后,操作系统会将发给台球游戏的鼠标消息发给钩子处理程序,从而钩子处理程序获知了鼠标位置信息,再通过事先准备好的球体识别功能函数识别出母球和目标球球心及半径。具备这些信息后就能准确计算出两球相撞后的前进方向并画出球的前进路线。如果路线指向球洞就表明成功瞄准,玩家借以代替目测瞄准。
其中球体中心识别功能利用了键盘钩子。游戏者将鼠标移至球体中心位置附近后按下键盘上的特定键,比如“t”键。钩子程序捕获台球游戏的该按键消息之后,结合此时捕获的鼠标坐标信息,通过预先编写好的球体识别函数找到 球心准确坐标。该函数以鼠标位置为中心搜索球体边缘并计算出球心坐标,其中的几何知识与钩子技术无关,本文不做介绍。
4 效果分析
利用钩子程序辅助台球游戏投入实验之后,能实时准确地反馈台球游戏中鼠标的位置信息,也能截获键盘的按键消息。只是键盘消息中的按键值与通常的ASCII码并完全不一致,键盘上也存在一些非ASCII符号,所以在编写键盘钩子程序的时候需要查阅键盘键值表。
本文实验采用.net平台下的C#语言编写钩子程序,使用者感受到系统性能受到一定影响。分析原因可能有两个:一是钩子程序挂接在操作系统的监控链表之后给系统带来了一定的负荷[3],二是C#程序依赖于.net Framework 2.0以上的平台,而使用者所用的计算机型号较老,性能不佳,如果用C++改写此程序可能性能会更好一些。
5 结语
操纵电脑游戏获得的好处是有限的,但是钩子技术带给人的启发意义是较大的。利用钩子监控各类消息的功能,很容易理解电脑安全中的数据窃取以及相应的安全防范技术原理。这对于推进编程技术,促进电脑安全软件的发展很有意义。
参考文献:
[1]施琛.基于钩子函数的应用程序快捷键设置[j].计算机与数字工程, 2013年第1期:92-94
[2]高曉.Hook及其防御技术探析[j]. 长春工业大学学报(自然科学版), 2013年12月第34卷第6期:686-691
[3]魏东.利用日志钩子函数实现Windows系统信息的捕获[j].昆明理工大学学报, 2002 8月第27卷第4期:86-89
作者简介:秦丹,讲师,硕士,研究方向:人工智能