在 DOS 系统中编程,经常会采取截取中断向量的技术:我们可以设置新的中断服务程序,当系统其他的程序调用这个中断时,就让它先调用我们自己设置的新的中断服务程序,然后再调用原来的中断服务程序,这样就能够获得非凡的控制权。许多优秀的软件和大多数 DOS 病毒程序都采用了这个方法。
在 Windows 中,我们也可以采取类似技术。当系统调用某个 API 函数时,就会先进入我们自己的函数,然后再调用原来的 API 函数,这样,我们的程序就可以取得更多的控制权,我们就可对 Windows 系统中的任意一个函数调用进行动态拦截、跟踪、修改和恢复,就可让 Windows 系统中的任意一个函数按我们的设想工作。这种技术有许多名称,比如“陷阱技术”、“重入技术”等
HOOK使我们可以控制系统事件的发生和处理,能偶预演和修改事件和消息,在系统范围内阻止系统事件和消息的发生
首先,用Setwindowshookex(idhook INteger;ipfn:TFN:TFNHookProc;hmod:WINST,dwThreadID):Hhook;stdcall;这个函数来设置HOOK,该函数返回一个HOOK的句柄,我们必须保持这个句柄,以在程序中使用
IDHOOK 是指要安装的HOOK的类型,包括:
WH_CALLWNDPROC 窗口函数过滤,窗口函数收到消息时,调用这个挂钩函数
WH_CALLWNDPROCRET 建立用于监视窗口函数处理过的消息的挂钩过程
WH_CBT 处理大多数窗口管理,鼠标键盘消息前会调用这个挂钩函数
WH_DEBUG 调试过滤器,在任何WINDOWS挂钩函数之前调用这个挂钩函
WH_GETMESSAGE 消息过滤器,在应用程序队列消息队列中检索到消息时调用这个挂钩函数
WH_HARDWARE 硬件消息过滤器,在应用程序消息队列中检索到硬件消息时调用这个函数
WH_JOURNALPLAYBACK 在系统消息队列检索到消息时调用这个挂钩函数,用于在消息队列中插入一个系统事件
WH_JOURNALRECORD 一个事件从系统队列中被请求时调用这个挂钩函数,用于记录系统事件
WH_MOUSE 鼠标过滤器,从应用程序消息队列中检索到WH_KEYDOWN和WH_KEYUO时调用这个函数
WH_KEYBOARD_LL 一个低层的键盘过滤器
WH_MOUSE_LL: 一个低层的鼠标过滤器
WH_MSGFILTER 特殊消息过滤器,应用程序的对话框,菜单,信息框处理一个消息时调用这个挂钩函数
WH_SHELL 外壳应用过滤器,窗口被创建和释放或者外壳过程需要激活时,调用这个挂钩函数
LPFN WINDOW挂钩函数的回调函数的地址,该函数为TFNHOOKPROD类型
,回调函数类型如下
TFNHOOKPROC=FUNCTION(code:integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;
其中CODE为系统指示符,wParam和lParam为附加消息,根据不同的消息监视类型而不同,只要在程序中建立
这样一个函数再通过setwindowshookex函数将它加入到消息监视连中就可以处理消息了
hmod包含挂钩回调函数EXE和DLL的hInstalce变量
dwThreadID用于表示一个与挂钩关联的线程,为0时表示该HOOK可在任何线程中使用
第二,使用挂钩函数
使用挂钩链中的下一个挂钩函数CallNextHookEx(HookHandle,Code,wparam,lparam);
HookHandle是SetWindowHooKEx函数的返回值,CODE为系统指示标记,WPARAM和LPARAM为
附加参数,根据不同的消息监视类型而不同
第三,使用脱钩函数
用UnhookWindowsHookEx(HookHandle)来释放挂钩
由于钩子函数必须在独立的模块中,也就是首先必须生成一个DLL框架,然后再其中加入狗子函数代码
以及其他相关的函数代码,HOOK要再DLL中启动和调用
1 先生成一个DLL框架
2 编写自己的钩子过滤函数,钩子过滤函数必须为回调函数,形式为
function KeyHookProc(iCode:Ingeter;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export
3 在生成的DLL框架中加入自己钩子的处理函数
4.用setwindowsHookEx函数安装HOOK
5 用UNHOOKWINDOWSHOOKEX卸载钩子
第四 DLL的初始化和清理操作
DLL的入口和出口函数,用来执行DLL的初始化和释放的操作。还要再DLL中加入自己的入口函数
全局变量DLLProc是一个过程的指针。定义在SysUtils单元,即为DLL的入口。在此用我们的函数替换了它的入口
这个函数必须符合以下要求【其实就是一个回调函数】。
procedure DLLenterPoint(dwReason:DWORD);far;stdcall;
dwReason参数由四种类型
DLL_PROCESS_ATTACH: 进程进入时
DLL_PROCESS_DETACH: 进程退出时
DLL_THREAD_ATTACH:线程进入时
DLL_THREAD_DETACH 线程退出时
初始化部分以下面的形式出现:
DLLProc := @DLLEnterPoint;
DLLEnterPoint(DLL_PROCESS_ATTACH)