WinAPI【钩子相关函数】 HOOK例解

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

WinAPI: SetWindowsHookEx - 设置钩子

 

提示: 如果要设置系统级钩子, 钩子函数必须在 DLL 中.

SetWindowsHookEx(
  idHook: Integer;   {钩子类型}
  lpfn: TFNHookProc; {函数指针}
  hmod: HINST;       {包含钩子函数的模块(EXE、DLL)句柄; 一般是 HInstance; 如果是当前线程这里可以是 0}
  dwThreadId: DWORD  {关联的线程; 可用 GetCurrentThreadId 获取当前线程; 0 表示是系统级钩子}
): HHOOK;            {返回钩子的句柄; 0 表示失败}

//钩子类型 idHook 选项:
WH_MSGFILTER       = -1; {线程级; 截获用户与控件交互的消息}
WH_JOURNALRECORD   = 0;  {系统级; 记录所有消息队列从消息队列送出的输入消息, 在消息从队列中清除时发生; 可用于宏记录}
WH_JOURNALPLAYBACK = 1;  {系统级; 回放由 WH_JOURNALRECORD 记录的消息, 也就是将这些消息重新送入消息队列}
WH_KEYBOARD        = 2;  {系统级或线程级; 截获键盘消息}
WH_GETMESSAGE      = 3;  {系统级或线程级; 截获从消息队列送出的消息}
WH_CALLWNDPROC     = 4;  {系统级或线程级; 截获发送到目标窗口的消息, 在 SendMessage 调用时发生}
WH_CBT             = 5;  {系统级或线程级; 截获系统基本消息, 譬如: 窗口的创建、激活、关闭、最大最小化、移动等等}
WH_SYSMSGFILTER    = 6;  {系统级; 截获系统范围内用户与控件交互的消息}
WH_MOUSE           = 7;  {系统级或线程级; 截获鼠标消息}
WH_HARDWARE        = 8;  {系统级或线程级; 截获非标准硬件(非鼠标、键盘)的消息}
WH_DEBUG           = 9;  {系统级或线程级; 在其他钩子调用前调用, 用于调试钩子}
WH_SHELL           = 10; {系统级或线程级; 截获发向外壳应用程序的消息}
WH_FOREGROUNDIDLE  = 11; {系统级或线程级; 在程序前台线程空闲时调用}
WH_CALLWNDPROCRET  = 12; {系统级或线程级; 截获目标窗口处理完毕的消息, 在 SendMessage 调用后发生} 

 

WinAPI: UnhookWindowsHookEx - 卸掉钩子

UnhookWindowsHookEx(

  hhk: HHOOK {钩子句柄}

): BOOL;     {True/False}

 

WinAPI: CallNextHookEx - 调用下一个钩子

 

CallNextHookEx(
  hhk: HHOOK;     {当前钩子的句柄}
  nCode: Integer; {钩子代码; 就是给下一个钩子要交待的}
  wParam: WPARAM; {要传递的参数; 由钩子类型决定是什么参数}
  lParam: LPARAM  {要传递的参数; 由钩子类型决定是什么参数}
): LRESULT;       {会返回下一个钩子执行后的返回值; 0 表示失败}

//参数 nCode 的可选值:
HC_ACTION      = 0;     {}
HC_GETNEXT     = 1;     {}
HC_SKIP        = 2;     {}
HC_NOREMOVE    = 3;     {}
HC_NOREM = HC_NOREMOVE; {}
HC_SYSMODALON  = 4;     {}
HC_SYSMODALOFF = 5;     {}

 

 

 

目前对钩子的理解:
 
譬如我们用鼠标在某个窗口上双击了一次, 或者给某个窗口输入了一个字母 A; 首先发现这些事件的不是窗口, 而是系统!然后系统告诉窗口: 喂! 你让人点了, 并且是连续点了两鼠标, 你准备怎么办? 或者是系统告诉窗口: 喂! 有人向你家里扔砖头了, 不信你看看, 那块砖头是 A. 

这时窗口的对有些事件会忽略、对有些事件会做出反应:譬如, 可能对鼠标单击事件忽略, 窗口想: 你单击我不要紧, 累死你我不负责; 但一旦谁要双击我, 我会马上行动, 给你点颜色瞧瞧!这里窗口准备要采取的行动, 就是我们提前写好的事件.
用 Windows 的话说, 窗口的事件就是系统发送给窗口的消息; 窗口要采取的行动(事件代码)就是窗口的回调函数.但是! 往往隔墙有耳. 系统要通知给窗口的"话"(消息), 可能会被另一个家伙(譬如是一个贼)提前听到!有可能这个贼就是专门在这等情报的, 贼知道后, 往往在窗口知道以前就采取了行动!
并且这个贼对不同的消息会采取不同的行动方案, 它的行动方案一般也是早就准备好的;当然这个贼也不是对什么消息都感兴趣, 对不感兴趣的消息也就无须制定相应的行动方案.

总结: 这个"贼"就是我们要设置的钩子; "贼"的"行动方案"就是钩子函数, 或者叫钩子的回调函数.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

{声明键盘钩子回调函数; 其参数传递方式要用 API 的 stdcall}
function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

var
  Form1: TForm1;

implementation

{$R *.DFM}

var
  hook: HHOOK; {定义一个钩子句柄}

{实现键盘钩子回调函数}
function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
  if (wParam = 65) then Beep; {每拦截到字母 A 会发声}
  Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;

{设置键盘钩子}
procedure TForm1.FormCreate(Sender: TObject);
begin
  hook := SetWindowsHookEx(WH_KEYBOARD, @KeyHook, 0, GetCurrentThreadID);
end;

{释放键盘钩子}
procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnhookWindowsHookEx(hook);
end;

end.

尽管这个例子已经很简单了, 但还不足以让人明白彻底; 下面还得从更简单的开始.

 
钩子函数虽然不多, 但其参数复杂, 应该从参数入手才能深入进去.

UnhookWindowsHookEx 只需要 SetWindowsHookEx 返回的钩子句柄作参数, 这个简单;

先看看 SetWindowsHookEx 的声明:
SetWindowsHookEx(
  idHook: Integer;   {钩子类型}
  lpfn: TFNHookProc; {函数指针}
  hmod: HINST;       {包含钩子函数的模块(EXE、DLL)的句柄}
  dwThreadId: DWORD  {关联的线程}
): HHOOK;
第一个参数非常麻烦, 从后面说:

参数四 dwThreadId : 在设置全局钩子时这个参数一般是 0, 表示关联所有线程; 本例是线程级的钩子, 所以是
GetCurrentThreadId.

参数三 hmod: 是模块实例的句柄, 在 EXE 和 DLL 中都可以用 HInstance 得到当前实例的句柄; 直接用 API 也可以:
GetModuleHandle(nil).

参数二 lpfn: 是钩子函数的指针, 用 @ 和 Addr 函数都可以得到函数指针; 这里的关键是那个钩子函数:
首先不同的钩子类型对应着不同的钩子函数结构, Win32 共有 14 种钩子类型, 这是 详细注释;
本例用的是键盘钩子, 键盘钩子的回调函数的参数结构在 这里, 我们定义的函数名无所谓, 参数必须按照Windows的规定来.
还有, 这个回调函数的调用惯例必须是: stdcall; 我们在上例中是先在接口区声明, 如果不要声明直接实现, 也不能忘了这个 stdcall.

根据以上说明, 做如下修改:
SetWindowsHookEx 的参数有变通;
并且取消了钩子函数在接口区的声明, 是直接实现的;
取消了拦截条件, 现在只要是键盘消息全都拦截.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

var
  hook: HHOOK; {定义一个钩子句柄}

{现在这个钩子函数没有在接口区声明, 这里必须指定参数调用方式: stdcall}
function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  Beep;
  Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;

{设置键盘钩子}
procedure TForm1.FormCreate(Sender: TObject);
begin
  hook := SetWindowsHookEx(WH_KEYBOARD, Addr(KeyHook), HInstance, GetCurrentThreadId);
end;

{释放键盘钩子}
procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnhookWindowsHookEx(hook);
end;

end.
钩子函数为什么非得使用 stdcall 调用机制? 因为钩子函数不是被应用程序调用, 而是被系统调用的
 
使用钩子函数 建立一个全局的鼠标钩子 
分两步:
一、建立 DLL, 并在 DLL 实现钩子的设置、释放和钩子函数;
二、再建一个工程调用测试.
 

第一步: 做 DLL



先建立一个 DLL 工程, 自动初始的代码如下(去掉注释了):
 
library Project1;

uses
  SysUtils,
  Classes;

{$R *.res}

begin
end.


//把工程保存为 MyHook.dpr, 并实现如下:

library MyHook;

uses
  SysUtils,
  Windows,  {钩子函数都来自 Windows 单元}
  Messages, {消息 WM_LBUTTONDOWN 定义在 Messages 单元}
  Classes;

{$R *.res}

var
  hook: HHOOK; {钩子变量}

{钩子函数, 鼠标消息太多(譬如鼠标移动), 必须要有选择, 这里选择了鼠标左键按下}
function MouseHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  if wParam = WM_LBUTTONDOWN then
  begin
    MessageBeep(0);
  end;
  Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;

{建立钩子}
function SetHook: Boolean; stdcall;
begin
  hook := SetWindowsHookEx(WH_MOUSE, @MouseHook, HInstance, 0);
  Result := hook <> 0;
end;

{释放钩子}
function DelHook: Boolean; stdcall;
begin
  Result := UnhookWindowsHookEx(hook);
end;

{按 DLL 的要求输出函数}
exports
  SetHook name 'SetHook',
  DelHook name 'DelHook',
  MouseHook name 'MouseHook';

//SetHook, DelHook, MouseHook; {如果不需要改名, 可以直接这样 exports}

begin
end.
注意: SetWindowsHookEx 的第一个参数 WH_MOUSE 说明这是个鼠标钩子; 第四个参数 0 说明是全局的.
鼠标钩子回调函数的格式在 这里

然后按 Ctrl+F9 编译, 在工程目录下会生成一个和工程同名的文件, 这里是: MyHook.dll.
 

第二步: 调用

新建工程后, 保存, 并把刚才制作的 MyHook.dll 复制到这个工程目录下;
然后添加两个按钮, 实现如下:
 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

  {DLL 中的函数声明}
  function SetHook: Boolean; stdcall;
  function DelHook: Boolean; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{DLL 中的函数实现, 也就是说明来自那里, 原来叫什么名}
function SetHook; external 'MyHook.dll' name 'SetHook';
function DelHook; external 'MyHook.dll' name 'DelHook';

{建立钩子}
procedure TForm1.Button1Click(Sender: TObject);
begin
  SetHook;
end;

{销毁钩子}
procedure TForm1.Button2Click(Sender: TObject);
begin
  DelHook;
end;

end.
测试: 点击第一个按钮后, 钩子就启动了; 这是不管鼠标在哪点一下鼠标左键都会 "呯" 的一下; 点击第二个按钮可以收回钩子. 

下面是动态调用的方法, 功能和上面完全一直:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{要先要定义和 DLL 中同样参数和返回值的的函数类型}
type
  TDLLFun = function: Boolean; stdcall;
  {现在需要的 DLL 中的函数的格式都是这样, 定义一个就够了}

var
 h: HWND;                   {声明一个 DLL 句柄}
 SetHook, DelHook: TDLLFun; {声明两个 TDLLFun 变量}


{载入 DLL 并调用其函数}
procedure TForm1.Button1Click(Sender: TObject);
begin
  h := LoadLibrary('MyHook.dll'); {载入 DLL 并获取句柄}
  if h<>0 then
  begin
    SetHook := GetProcAddress(h, 'SetHook'); {让 SetHook 指向 DLL 中相应的函数}
    DelHook := GetProcAddress(h, 'DelHook'); {让 DelHook 指向 DLL 中相应的函数}
  end else ShowMessage('Err');

  SetHook; {执行钩子建立函数, 这里的 SetHook 和它指向的函数是同名的, 也可以不同名}
end;

{销毁钩子, 并释放 DLL}
procedure TForm1.Button2Click(Sender: TObject);
begin
  DelHook;        {执行钩子释放函数}
  FreeLibrary(h); {释放 DLL 资源}
end;

end.
为什么全局钩子非要在 DLL 中呢?
因为每个 EXE 都是一个独立而封闭的进程; 而 DLL 则是面向系统的公用资源.
如果一个钩子不是面向系统的, 恐怕意义不大; 所以在实用中, 钩子是离不开 DLL 的
 
  
钩子链和 CallNextHookEx 的返回值
SetWindowsHookEx 函数的第一个参数表示钩子类型, 共有 14 种选择, 前面我们已经用过两种:
WH_KEYBOARD、WH_MOUSE.

系统会为每一种类型的钩子建立一个表(那就是 14 个表), 譬如某个应用程序启动了键盘钩子, 我们自己的程序也启动了键盘钩子, 同样是键盘钩子就会进入同一个表. 这个表(可能不止一个, 可能还会有鼠标钩子等等)就是传说中的"钩子链".

假如某个钩子链中共进来了三个钩子(譬如是: 钩子A、钩子B、钩子C 依次进来), 最后进来的 "钩子C" 会先执行.
是不是先进后出? 我觉得应该说成: 后进先出! 这有区别吗? 有! 因为先进来的不一定出得来.
最后进了的钩子会最先得到执行, 先前进来的钩子(钩子A、钩子B)能不能得到执行那还得两说, 这得有正在执行的 "钩子C" 说了算.
如果 "钩子C" 的函数中包含了 CallNextHookEx 语句, 那么 "钩子A、钩子B" 就有可能得以天日; 不然就只有等着相应的
UnhookWindowsHookEx 来把它们带走(我想起赵本山的小品...).

这时你也许会想到: 这样太好了, 我以后就不加 CallNextHookEx , 只让自己的钩子"横行"; 但如果是你的钩子先进去的呢?
所以 Windows 建议: 钩子函数要调用 CallNextHookEx, 并把它的返回值当作钩子函数自己的返回值.

CallNextHookEx 同时要给钩子链中的下一个(或许应该叫上一个)钩子传递参数(譬如在键盘消息中按了哪个键). 一个键盘钩子和鼠标钩子的参数一样吗? 当然不一样, 所以它们也不在一个 "链" 中啊; 同一个链中的钩子的类型肯定是一样的.
再聊聊钩子函数的返回值:
在这之前, 钩子函数的返回值, 我们都是遵循 Windows 的惯例, 返回了 CallNextHookEx 的返回值.
如果 CallNextHookEx 成功, 它会返回下一个钩子的返回值, 是个连环套;
如果 CallNextHookEx 失败, 会返回 0, 这样钩子链也就断了, 只有当前钩子还在执行任务.

不同类型的钩子函数的返回值是不同的, 对键盘钩子来讲如果返回一个非 0 的值, 表示它处理完以后就把消息给消灭了.
换句话说:
如果给键盘的钩子函数 Result := 0; 说明消息被钩子拦截并处理后就给 "放" 了;
如果给键盘的钩子函数 Result := 1; 说明消息被钩子拦截并处理后又给 "杀" 了.

在下面的例子中, 我们干脆不使用 CallNextHookEx (反正暂时就我一个钩子), 直接给返回值!
//示例代码:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

  {钩子函数声明}
  function MyKeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  hook: HHOOK;

function MyKeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
  Form1.Memo1.Lines.Add(IntToStr(wParam)); {参数二是键值}
  Result := 0; {分别测试返回 0 或非 0 这两种情况}
end;

{派出钩子}
procedure TForm1.Button1Click(Sender: TObject);
begin
  hook := SetWindowsHookEx(WH_KEYBOARD, MyKeyHook, HInstance, GetCurrentThreadId);
  Memo1.Clear;
  Text := '钩子启动';
end;

{收回钩子}
procedure TForm1.Button2Click(Sender: TObject);
begin
  UnhookWindowsHookEx(hook);
  Text := '钩子关闭';
end;

{如果忘了收回钩子...}
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if hook<>0 then UnhookWindowsHookEx(hook);
end;

end.
小秘密: 发现没有, 这次在 SetWindowsHookEx 时, 第二参数(函数地址), 没有使用 @、也没有用 Addr, 怎么也行呢?
因为函数名本身就是个地址.
 
  
使用钩子函数 数据传递
 
上一个例子是从 DLL 中接受数据, 那怎么给 DLL 传递数据呢? 还有, 在接受数据时, 让 Timer 一直在那扫描也不是个好办法呀. 本例解决了这些问题(但不知解决了博友 "鹏" 的问题没有?).

为了方便测试, 提供一个源码下载吧: http://files.cnblogs.com/del/MouseHook_2.rar
本例效果图(和上一例是一样的):


DLL 文件:
library MyHook;

uses
  SysUtils,
  Windows,
  Messages,
  Classes;

{$R *.res}

const WM_MyMessage = WM_USER + 1; {自定义消息}

var
  hook: HHOOK;
  info: string;
  h: HWND; {用作外部窗口的句柄}

{获取外部窗口的句柄}
function SetHWnd(hwnd: HWND): Boolean; stdcall;
begin
  h := hwnd;
  Result := True;
end;

function MouseHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  case wParam of
    WM_MOUSEMOVE   : info := '鼠标位置';
    WM_LBUTTONDOWN : info := '按下';
    WM_LBUTTONUp   : info := '放开';
  end;
  info := Format('%s: %d,%d', [info, PMouseHookStruct(lParam)^.pt.X, PMouseHookStruct(lParam)^.pt.Y]);

  {通过消息把数据传递给指定窗口}
  PostMessage(h, WM_MyMessage, 0, Integer(PChar(info)));

  Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;

function SetHook: Boolean; stdcall;
const
  WH_MOUSE_LL =14;
begin
  hook := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, HInstance, 0);
  Result := hook <> 0;
end;

function DelHook: Boolean; stdcall;
begin
  Result := UnhookWindowsHookEx(hook);
end;

exports SetHook, DelHook, MouseHook, SetHWnd;
begin
end.
测试代码:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

const WM_MyMessage = WM_USER + 1;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure MyMessage(var msg: TMessage); message WM_MyMessage; {定义一个消息方法接受消息}
  end;

  function SetHook: Boolean; stdcall;
  function DelHook: Boolean; stdcall;
  function SetHWnd(hwnd: HWND): Boolean; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function SetHook; external 'MyHook.dll';
function DelHook; external 'MyHook.dll';
function SetHWnd; external 'MyHook.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetHook;
  SetHWnd(Handle);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  DelHook;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.Caption := '安装钩子';
  Button2.Caption := '载卸钩子';
  FormStyle := fsStayOnTop; {为了测试, 让窗口一直在前面}
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DelHook;
end;

{把接受到的内容显示在窗体}
procedure TForm1.MyMessage(var msg: TMessage);
begin
  Text := PChar(msg.LParam);
end;

end.
测试窗体:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 78
  ClientWidth = 271
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 48
    Top = 32
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 144
    Top = 32
    Width = 75
    Height = 25
    Caption = 'Button2'
    TabOrder = 1
    OnClick = Button2Click
  end
end

hook ie浏览器 用easyhook库修改IE浏览器api,获取用户浏览信息,并根据浏览信息进行分析,结果存放httplog.txt中 立即下载

相关推荐

利用钩子机制取得Windows的消息监控权

利用钩子机制取得Windows的消息监控权       我们知道,Windows系统是建立在消息传递机制基础上的,几乎所有的程序活动都由消息来驱动。Windows的钩子机制可以看作是一个消息中转站,控制系统发出消息的处理和传递,利用钩子,我们可以截获系统发给应用程序的消息,经过处理后决定是否将消息再发给下一个应用程序。 利用钩子的这一特性,我们可以创建一个监控程序,用来收集和控制系统发出的消息。

小发猫 2749

Windows API用户是否在使用鼠标或键盘

《编程之美》1.10的最后提到了一个问题,就是windows中什么api能了用户是否在使用鼠标或键盘,或者发现用户在几秒之内没有鼠标、键盘的输入? 网上搜索了一下资料,觉得大概有两种方法: (1)GetInputState 函数原型: BOOL GetInputState(VOID); 函数功能:该函数确定在当前线程的消息队列中是否有要处理的鼠标,键盘消息. 注意事项:返回值指定是否发

华秋实的专栏 1万+

在Visual C++ 6.0下应用Win32系统钩子技术

一、引言钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。钩子的种类很多,每种钩子可以截获并处理相应的消息,每当特定的消息发出,在到达目的窗口之前,钩子程序先行截获该消息、得到对此消息的控制权。此时钩子函数可以对截获的消息进行加工处理,甚至可以强制结束消息的传递。这有点类似与MFC中的PreTranslateMessage函数,所不同的是该函数只能用于拦截本进程中的消息,而对系统

神经网络爱好者 1311

DELPHI HOOK随手笔记

在 DOS 系统中编程,经常会采取截取中断向量的技术:我们可以设置新的中断服务程序,当系统其他的程序调用这个中断时,就让它先调用我们自己设置的新的中断服务程序,然后再调用原来的中断服务程序,这样就能够获得非凡的控制权。许多优秀的软件和大多数 DOS 病毒程序都采用了这个方法。 在 Windows 中,我们也可以采取类似技术。当系统调用某个 API 函数时,就会先进入我们自己的函数,然后再调用原...

kinvsn的博客 1358

Windows HOOK钩子技术

Windows HooK钩子技术是指基于Windows中窗口的程序的消息处理里机制,对系统或者进程中的消息进行截获和处理,并将截获和处理的消息在重新处理和发送,使其可以实现不同的功能。 钩子技术分为系统钩子技术和线程钩子技术 系统钩子:是用于监视真个系统中的消息的钩子技术,因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL) 中。做好之后使用其他程序将钩子挂载到系统的进程中。 线程钩子:指的是对指定线程进行监视。 钩子原理 在使用钩子技术的时候,WINDOWS会先在内存中创

qq_43812868的博客 2862

对于HOOK函数的一点认识

对于HOOK函数的一点认识maco·cpcw        这种函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。当然,这么做也是需要付出一定的代价的。由于多了这么一道处理过程,系统性能会受到一定的影响,所以大家在必要的时候才使用“钩子”,并在使用完毕及时将其删除。  首先让我们

iBreathe的专栏 3256

一个Hook钩子

设置HOOK HHOOK WINAPI SetWindowsHookEx( __in int idHook, \\钩子类型 __in HOOKPROC lpfn, \\回调函数地址 __in HINSTANCE hMod, \\实句柄 __in DWORD dwThreadId); \\线程ID ) HHOOK SetWindowsHookEx( int idHook, // 钩子的类型,即它处理的消息类型 HOOKPROC lpfn, // 钩子子程的地址指针.

目前打算换一个工作,有招聘windows c++方向的也欢迎联系,北京、济南 最好 981

钩子函数(HOOK)完整的教程

钩子函数(HOOK)完整的教程 基本概念  钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,...

心情第一 2万+

Windows核心编程 HOOK

Windows核心编程 HOOK ,全局钩子,局部钩子,以及相关API

qq_61553520的博客 1793

导入地址表钩子IAT HOOK以及内联钩子INLINE HOOK

0x00 HOOK简介 HOOK技术是一种非常古老的技术。不管是Windows下的Hook还是Linux下的Hook都是一脉相承,变了外表但实质都是一样的。Hook的意思是钩子,我们通过Hook可以改变进程的执行流程。一般HOOK技术与远程线程注入或者全局钩子来配合使用。前者使我们跳转我们想要执行的代码,后者可以隐藏我们的DLL。在这里我们会通篇进行介绍。 PS 每一篇我都会给一个实,我觉得...

輚至消亡 1789

HOOK与注入

HOOK和注入技术经常被恶意代码使用。利用HOOK和注入技术,恶意代码提高了执行隐蔽性,增加了恶意代码分析难度,在某些情况下还能实现权限提升和内存常驻。 HOOK技术 挂钩(HOOK)就是在来往信息间安装“钩子”,钩取来往信息。 在用户层,常见的Hook技术有: ①消息钩子 ②Inline Hook ③IAT Hook 消息钩子 原理: 用户对应用程序的各种操作(eg:键盘输入、点击、移动等)都会产生事件;发生事件时,操作系统会把该事件对应的消息发送给相应的应用程序,应用程序分析收到的信息后执行相应的动作。

weixin_43781139的博客 5808

HOOK函数(一)——进程内HOOK

  什么是HOOK呢?其实很简单,HOOK就是对Windows消息进行拦截检查处理的一个函数。在Windows的消息机制中,当用户产生消息时,应用程序通过调用GetMessage函数取出消息,然后把消息放入到消息队列,再使用消息调度函数DispatchMessage函数讲消息调度给系统,Windows系统会调用创建窗口类时制定的窗口过程中进行次消息的处理。而HOOK函数的话,就可以对此消...

aa748597605的博客 769

VC++内联钩子实战:从原理到实现Windows API Hook

API Hook(应用程序编程接口钩子)是一种在Windows平台广泛使用的底层技术,其核心原理是通过拦截和修改函数调用流程,实现对系统或应用程序行为的监控与干预。这项技术通过修改目标函数在内存中的机器码,插入自定义跳转指令,从而在执行流到达目标函数时,能够先执行开发者预设的代理函数。从技术价值看,API Hook为软件调试、行为分析、性能监控和安全研究提供了强大的底层观察与控制能力,尤其适用于需要实时追踪系统调用、分析软件内部逻辑或实现兼容性修复等场景。结合热词中提到的“系统全局”监控需求,内联钩子(In

weixin_30388677的博客 327

windows Hook技术 限制鼠标仅能在指定区域活动

hook (Windows系统机制) • Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或 “钩子” 。在对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程 序就会收到系统的通知,这时程序就能在第一时间对该事件做出响应。 • 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定 窗口...

快乐小半半的博客 1415

鼠标钩子源代码

using System;using System.Runtime.InteropServices;using System.Reflection;using System.Threading;using System.Windows.Forms;namespace tuku{  ///  /// 这个类可以让你得到一个在运行中程序的所有键盘或鼠标事件 /// 并且引发一个带KeyEventArg

邻舍技术博客 2270

键盘HOOK简单学习

对于系统钩子,该参数为钩子函数所在的DLL句柄。HOOK代码的构件中比较关键的就是回调函数,它意味着我的HOOK要实现什么样的功能,是仅拦截,还是将获取的信息传递到其他文件中之类的,现在好像还没必要看勾链,所以代码中的CallNextHookEx因该只是实现非目的进程不拦截信息。当我们通过exe建立钩子后,一旦有程序发生键盘输入,OS就会自动把我们提前传入句柄的DLL注入相关程序,进而调用回调函数,实现对消息的处理。idHook钩子的拦截消息类型,选择钩子程序的拦截范围,具体值参考文章结尾的消息类型。

2303_79822944的博客 2009
上一篇: char*和CString转换
下一篇: POSTTHREADMESSAGE
ShenRui
博客等级 码龄19年 63粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值