📄 tut24.html
字号:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="lancelot">
<meta name="GENERATOR" content="Mozilla/4.51 [en] (Win95; I) [Netscape]">
<title>Iczelion's Win32 Assembly Tutorial 24: Windows Hooks</title>
</head>
<body text="#C0C0C0" bgcolor="#000000" link="#FFFF00" vlink="#C0C0C0" alink="#C0FFC0">
<center>
<h1>
<font face="Arial,Helvetica"><font color="#999900">Tutorial 24: Windows
Hooks</font></font></h1></center>
<font face="Arial,Helvetica"><font size=-1>We will learn about Windows
hooks in this tutorial. Windows hooks are very powerful. With them, you
can poke inside other processes and sometimes alter their behaviors.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>Download the example <a href="files/tut24.zip">here</a>.</font></font>
<h3>
<font face="Arial,Helvetica"><font color="#CC6600">Theory:</font></font></h3>
<font face="Arial,Helvetica"><font size=-1>Windows hooks can be considered
one of the most powerful features of Windows. With them, you can trap events
that will occur, either in your own process or in other processes. By "hooking",
you tell Windows about a function, filter function also called hook procedure,
that will be called everytime an event you're interested in occurs. There
are two types of them: local and remote hooks.</font></font>
<ul>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">Local
hooks</font> trap events that will occur in your own process.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#D9D900">Remote
hooks</font> trap events that will occur in other process(es). There are
two types of remote hooks</font></font></li>
<ul>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">thread-specific</font>
traps events that will occur in a specific thread in other process. In
short, you want to observe events in a specific thread in a specific process.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">system-wide</font>
traps all events destined for all threads in all processes in the system.</font></font></li>
</ul>
</ul>
<font face="Arial,Helvetica"><font size=-1>When you install hooks, remember
that they affect system performance. System-wide hooks are the most notorious.
Since ALL related events will be routed through your filter function, your
system may slow down noticeably. So if you use a system-wide hook, you
should use it judiciously and unhook it as soon as you don't need it. Also,
you have a higher chance of crashing the other processes since you can
meddle with other processes and if something is wrong in your filter function,
it can pull the other processes down to oblivion with it. Remember: Power
comes with responsibility.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>You have to understand how
a hook works before you can use it efficiently. When you create a hook,
Windows creates a data structure in memory, containing information about
the hook, and adds it to a linked list of existing hooks. New hook is added
in front of old hooks. When an event occurs, if you install a local hook,
the filter function in your process is called so it's rather straightforward.
But if it's a remote hook, the system must inject the code for the hook
procedure into the address space(s) of the other process(es). And the system
can do that only if the function resides in a DLL. Thus , if you want to
use a remote hook, your hook procedure must reside in a DLL. There is two
exceptions to this rule: journal record and journal playback hooks. The
hook procedures for those two hooks must reside in the thread that installs
the hooks. The reason why it must be so is that: both hooks deal with the
low-level interception of hardware input events. The input events must
be recorded/playbacked in the order they appeared. If the code of those
two hooks is in a DLL, the input events may scatter among several threads
and it is impossible to know the order of them. So the solution: the hook
procedure of those two hooks must be in a single thread only i.e. the thread
that installs the hooks.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>There are 14 types of hooks:</font></font>
<ul>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_CALLWNDPROC</font></b>
called when SendMessage is called</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_CALLWNDPROCRET</font></b>
called when SendMessage returns</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_GETMESSAGE</font></b>
called when GetMessage or PeekMessage is called</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_KEYBOARD</font></b>
called when GetMessage or PeekMessage retrieves WM_KEYUP or WM_KEYDOWN
from the message queue</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_MOUSE</font></b>
called when GetMessage or PeekMessage retrieves a mouse message from the
message queue</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_HARDWARE</font></b>
called when GetMessage or PeekMessage retrieves some hardware message that
is not related to keyboard or mouse.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_MSGFILTER </font></b>
called when a dialog box, menu or scrollbar is about to process a message.
This hook is local. It's specifically for those objects which have their
own internal message loops.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_SYSMSGFILTER</font></b>
same as WH_MSGFILTER but system-wide</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_JOURNALRECORD</font></b>
called when Windows retrieves message from the hardware input queue</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_JOURNALPLAYBACK</font></b>
called when an event is requested from the system's hardware input queue.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_SHELL</font></b>
called when something interesting about the shell occurs such as when the
task bar needs to redraw its button.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_CBT</font></b>
used specifically for computer-based training (CBT).</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_FOREGROUNDIDLE</font></b>
used internally by Windows. Little use for general applications</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><b><font color="#999900">WH_DEBUG</font></b>
used to debug the hooking procedure</font></font></li>
</ul>
<font face="Arial,Helvetica"><font size=-1>Now that we know some theory,
we can move on to how to install/uninstall the hooks.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>To install a hook, you call
SetWindowsHookEx which has the following syntax:</font></font>
<blockquote><b><font face="Arial,Helvetica"><font color="#009900"><font size=-1>SetWindowsHookEx
proto HookType:DWORD, pHookProc:DWORD, hInstance:DWORD, ThreadID:DWORD</font></font></font></b>
<ul>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">HookType</font>
is one of the values listed above, e.g., <b><font color="#999900">WH_MOUSE</font></b>,
<b><font color="#999900">WH_KEYBOARD</font></b></font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">pHookProc</font>
is the address of the hook procedure that will be called to process the
messages for the specified hook. If the hook is a remote one, it must reside
in a DLL. If not, it must be in your process.</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">hInstance</font>
is the instance handle of the DLL in which the hook procedure resides.
If the hook is a local one, this value must be NULL</font></font></li>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">ThreadID</font>
is the ID of the thread you want to install the hook to spy on. This parameter
is the one that determines whether a hook is local or remote. If this parameter
is NULL, Windows will interpret the hook as a system-wide remote hook that
affects all threads in the system. If you specify the thread ID of a thread
in your own process, this hook is a local one. If you specify the thread
ID from other process, the hook is a thread-specific remote one. There
are two exceptions to this rule: <b><font color="#999900">WH_JOURNALRECORD</font></b>
and <b><font color="#999900">WH_JOURNALPLAYBACK</font></b> are always local
system-wide hooks that are not required to be in a DLL. And <b><font color="#999900">WH_SYSMSGFILTER</font></b>
is always a system-wide remote hook. Actually it is identical to <b><font color="#999900">WH_MSGFILTER</font></b>
hook with ThreadID==0.</font></font></li>
</ul>
<font face="Arial,Helvetica"><font size=-1>If the call is successful, it
returns the hook handle in eax. If not, NULL is returned. You must save
the hook handle for unhooking later.</font></font></blockquote>
<font face="Arial,Helvetica"><font size=-1>You can uninstall a hook by
calling<b><font color="#FFFF00"> </font><font color="#009900">UnhookWindowsHookEx</font></b>
which accepts only one parameter, the handle of the hook you want to uninstall.
If the call succeeds, it returns a non-zero value in eax. Otherwise, it
returns NULL.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>Now that you know how to
install/uninstall hooks, we can examine the hook procedure.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>The hook procedure will
be called whenever an event that is associated with the type of hook you
have installed occurs. For example, if you install <b><font color="#999900">WH_MOUSE</font></b>
hook, when a mouse event occurs, your hook procedure will be called. Regardless
of the type of hook you installed, the hook procedure always has the following
prototype:</font></font>
<ul><b><font face="Arial,Helvetica"><font color="#009900"><font size=-1>HookProc
proto nCode:DWORD, wParam:DWORD, lParam:DWORD</font></font></font></b>
<br>
<ul>
<li>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFF00">nCode</font>
specifies the hook code.</font></font></li>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -