好久没写文章了,还记得年前面试了一家公司,为了检测一下我的学习能力,给了我一个任务,做一个自动登录并自动操作菜单的程序。
花了几天的时间研究了Hook以及使用WindowsAPI操作程序的知识,现在记录一下,也算是一次温习。
一丶Hook
在我看来Hook就是监测用户操作键盘(或虚拟键盘)以及鼠标的行为,对于Hook的理解我也不是很深入,也只是一点皮毛。
1. 实现Hook的步骤
①安装钩子
②监测键盘和鼠标的操作,用来实现相应的逻辑
③卸载钩子
2.安装钩子
钩子分两种:键盘钩子和鼠标钩子,而每一种钩子又可以分为全局钩子或局部勾子。
下面是安装钩子需要的Windows Message常量(网上找的)。
1 public enum HookType : int 2 { 3 /// <summary> 4 /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动 5 ///条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。 6 ///WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通 7 ///过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook 8 ///监视所有应用程序消息。 9 /// 10 ///WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间 11 ///过滤消息,这等价于在主消息循环中过滤消息。 12 /// 13 ///通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这 14 ///个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循 15 ///环里一样 16 /// </summary> 17 WH_MSGFILTER = -1, 18 /// <summary> 19 /// WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这 20 ///个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook 21 ///来回放。WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样 22 ///使用。WH_JOURNALRECORD是system-wide local hooks,它们不会被注射到任何行 23 ///程地址空间 24 /// </summary> 25 WH_JOURNALRECORD = 0, 26 /// <summary> 27 /// WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可 28 ///以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠 29 ///标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘 30 ///事件就是无效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定 31 ///Hook一样使用。WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处 32 ///理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实 33 ///时事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被 34 ///注射到任何行程地址空间 35 /// </summary> 36 WH_JOURNALPLAYBACK = 1, 37 /// <summary> 38 /// 在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and 39 ///WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使 40 ///用这个Hook来监视输入到消息队列中的键盘消息 41 /// </summary> 42 WH_KEYBOARD = 2, 43 /// <summary> 44 /// 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函 45 ///数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及 46 ///其它发送到消息队列中的消息 47 /// </summary> 48 WH_GETMESSAGE = 3, 49 /// <summary> 50 /// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之前调用 51 /// </summary> 52 WH_CALLWNDPROC = 4, 53 /// <summary> 54 /// 在以下事件之前,系统都会调用WH_CBT Hook子过程,这些事件包括: 55 ///1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; 56 ///2. 完成系统指令; 57 ///3. 来自系统消息队列中的移动鼠标,键盘事件; 58 ///4. 设置输入焦点事件; 59 ///5. 同步系统消息队列事件。 60 ///Hook子过程的返回值确定系统是否允许或者防止这些操作中的一个 61 /// </summary> 62 WH_CBT = 5, 63 /// <summary> 64 /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动 65 ///条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。 66 ///WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通 67 ///过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook 68 ///监视所有应用程序消息。 69 /// 70 ///WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间 71 ///过滤消息,这等价于在主消息循环中过滤消息。 72 /// 73 ///通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这 74 ///个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循 75 ///环里一样 76 /// </summary> 77 WH_SYSMSGFILTER = 6, 78 /// <summary> 79 /// WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。 80 ///使用这个Hook监视输入到消息队列中的鼠标消息 81 /// </summary> 82 WH_MOUSE = 7, 83 /// <summary> 84 /// 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时 85 /// </summary> 86 WH_HARDWARE = 8, 87 /// <summary> 88 /// 在系统调用系统中与其它Hook关联的Hook子过程之前,系统会调用 89 ///WH_DEBUG Hook子过程。你可以使用这个Hook来决定是否允许系统调用与其它 90 ///Hook关联的Hook子过程 91 /// </summary> 92 WH_DEBUG = 9, 93 /// <summary> 94 /// 外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是 95 ///激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子过程。 96 ///WH_SHELL 共有5钟情况: 97 ///1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁; 98 ///2. 当Taskbar需要重画某个按钮; 99 ///3. 当系统需要显示关于Taskbar的一个程序的最小化形式; 100 ///4. 当目前的键盘布局状态改变; 101 ///5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。 102 /// 103 ///按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接 104 ///收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自 105 ///己 106 /// </summary> 107 WH_SHELL = 10, 108 /// <summary> 109 /// 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE 110 ///Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就 111 ///会调用WH_FOREGROUNDIDLE Hook子过程 112 /// </summary> 113 WH_FOREGROUNDIDLE = 11, 114 /// <summary> 115 /// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之后调用 116 /// </summary> 117 WH_CALLWNDPROCRET = 12, 118 /// <summary> 119 /// 监视输入到线程消息队列中的键盘消息 120 /// </summary> 121 WH_KEYBOARD_LL = 13, 122 /// <summary> 123 /// 监视输入到线程消息队列中的鼠标消息 124 /// </summary> 125 WH_MOUSE_LL = 14 126 }