• 全局键盘钩子(WH_KEYBOARD)


    为了显示效果,在钩子的DLL中我们会获取挂钩函数的窗体句柄,这里的主程序窗体名为"TestMain",通过FindWindow查找。

    KeyBoardHook.dll代码

    library KeyBoardHook;
    
    { Important note about DLL memory management: ShareMem must be the
      first unit in your library's USES clause AND your project's (select
      Project-View Source) USES clause if your DLL exports any procedures or
      functions that pass strings as parameters or function results. This
      applies to all strings passed to and from your DLL--even those that
      are nested in records and classes. ShareMem is the interface unit to
      the BORLNDMM.DLL shared memory manager, which must be deployed along
      with your DLL. To avoid using BORLNDMM.DLL, pass string information
      using PChar or ShortString parameters. }
    
    uses
      SysUtils,Windows,Messages,
      Classes;
    
    var
      fHook:HHOOK;
      //执行挂钩程序的窗体句柄
      CallHandle:HWND;
    
    {$R *.res}
    
    //回调过程
    function HookProc(code:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
    var
      processid:Cardinal;
    begin
      //如果有键盘动作
      if code = HC_Action then
      begin
        //获取注入进程的进程id
        processid := GetCurrentProcessId;
        //如果CallHandle,则查找TestMain窗体句柄
        if CallHandle = 0 then
          CallHandle := FindWindow(nil,'TestMain');
        //获取按键状态 小于0表示按下,如果不做判断,按键按下或抬起都会执行SendMessage
        //下面发送WM_USER+101消息,此消息可以用自定义的消息标识发送
        if GetKeyState(wParam) < 0 then
          SendMessage(CallHandle,WM_USER+101,wParam,processid);
      end
      else
        //下一个钩子
        Result := CallNextHookEx(fHook,code,wParam,lParam);
    end;
    
    procedure SetHook;stdcall;
    begin
      //挂钩,这里没有做挂钩失败的提示
      fHook := SetWindowsHookEx(WH_KEYBOARD,@HookProc,HInstance,0);
    end;
    
    procedure StopHook;stdcall;
    begin
      //摘钩
      if fHook <> 0 then
        UnhookWindowsHookEx(fHook);
    end;
    
    exports
      SetHook name 'SetHook',
      StopHook name 'StopHook';
    
    begin
      //初始CallHandle为0
      CallHandle := 0;
    end.
    View Code

    TestKeyBoardHook主程序代码

    {
    此窗体用来执行挂钩,为了方便起见,我们把系统的按键返回到该窗体的Memo组件中进行
    显示,所以在dll中,做了获取主窗体的句柄的工作,以便发消息给主窗体,告诉它是哪个
    按键被按下
    }
    unit TestMain;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,TlHelp32;
    
    type
      TfrmTestMain = class(TForm)
        Memo1: TMemo;
        btn_SetHook: TButton;
        btn_StopHook: TButton;
        procedure btn_SetHookClick(Sender: TObject);
        procedure btn_StopHookClick(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }
        procedure WndProc(var Message: TMessage);override;
      public
        { Public declarations }
      end;
    
    var
      frmTestMain: TfrmTestMain;
    
    implementation
    
    procedure SetHook;stdcall;external 'KeyBoardHook';
    procedure StopHook;stdcall;external 'KeyBoardHook';
    
    {$R *.dfm}
    
    procedure TfrmTestMain.btn_SetHookClick(Sender: TObject);
    begin
      SetHook;
    end;
    
    procedure TfrmTestMain.btn_StopHookClick(Sender: TObject);
    begin
      StopHook;
    end;
    
    procedure TfrmTestMain.WndProc(var Message: TMessage);
    var
      hSnapShot:THandle;
      pEntry:TProcessEntry32;
      find:Boolean;
      proName:string;
    begin
      if Message.Msg = WM_USER+101 then
      begin
        //创建进程快照
        hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        pEntry.dwSize := SizeOf(pEntry);
        find := Process32First(hSnapShot,pEntry);                  
        while find do
        begin
          //取进程名字
          proName := pEntry.szExeFile;
          if pEntry.th32ProcessID = Message.LParam then Break;
          find := Process32Next(hSnapShot,pEntry);
        end;
        Memo1.Lines.Add('进程:' + proName + ',ID:' +IntToStr(Message.LParam)+'按下按键:'+Chr(Message.WParam));
        CloseHandle(hSnapShot);
      end;
      inherited;
    end;
    
    procedure TfrmTestMain.FormClose(Sender: TObject;
      var Action: TCloseAction);
    begin
      StopHook;
    end;
    
    end.
    View Code
  • 相关阅读:
    ingress-nginx-controller 504 gateway time-out 问题
    ansible的shell模板使用awk包含引号的问题
    Python selenium模块报错解决
    redis密码破解(multiprocessing的Pool多进程模式)-join方法小坑
    redis密码破解(Python使用multiprocessing分布式进程)
    redis密码破解(python使用redis模块)
    redis密码破解(python使用socket模块)
    修改云主机快照方式为live snapshot
    虚拟机重启错误,libvirtError:internal error:process exited while connecting to monitor
    如何解决高并发秒杀的超卖问题
  • 原文地址:https://www.cnblogs.com/key-ok/p/3429867.html
Copyright © 2020-2023  润新知