Windows システムのフックには非常に強力な機能があり、このテクノロジを使用すると、Windows システムのほぼすべてのメッセージを傍受、監視、処理できます。この技術は、さまざまなソフトウェア、特に監視、自動記録などのシステム監視機能を必要とするソフトウェアに広く使用できます。この記事では、読者の参考になることを願って、このトピックについて説明します。
1. フックの仕組みと種類
Windows アプリケーションはすべてメッセージ駆動型であり、アプリケーションの動作は受信するメッセージの種類と内容によって異なります。フックは、Dos 割り込みインターセプト処理メカニズムに似ています。フックは Windows メッセージ処理メカニズムのプラットフォームであり、さまざまなフックをインストールすることで、アプリケーションは指定されたウィンドウ内の特定のメッセージを監視し、ターゲット ウィンドウに到達する前にメッセージを処理するサブルーチンを設定できます。
Windows には 2 種類のフックがあり、1 つはシステム全体内のメッセージを監視するシステム フック (RemoteHook)、もう 1 つはプロセス内のメッセージのみをインターセプトするスレッド フック (LocalHook) です。システム フックの場合は、フック関数 (HookFunction) を Windows システムのダイナミック リンク ライブラリ (DLL) に実装する必要があります。スレッド フックの場合、フック関数は DLL または対応するアプリケーションに実装できます。これは、開発者がフックを作成するとき、Windows はまずシステム メモリ内にフックに関する情報を含むデータ構造を作成し、次にその構造を既存のフック リストに追加し、新しいフックが古いフックの前に並べ替えられるためです。フック。ローカルフックがインストールされている場合、イベントが発生すると、現在のプロセスのフック関数が呼び出されます。リモート フックの場合、システムはフック関数を他のプロセスのアドレス空間に挿入する必要があります。これを行うには、フック関数がダイナミック リンク ライブラリに存在する必要があるため、リモート フックを使用する場合は、次のように記述する必要があります。フック 関数をダイナミック リンク ライブラリに追加します。フックによって監視されるメッセージの種類として、Windows では合計次の種類が提供されています。 表 1 に示すように:
表 1. Windows メッセージの種類
メッセージタイプ定数識別子 | 価値 | メッセージの種類 | 適用範囲 |
WH_CALLWNDPROC | 4 | 窓口に送信されたメッセージ | スレッドまたはシステム |
WH_CALLWNDPROCRET | 12 | 窓から返されたメッセージ | スレッドまたはシステム |
WH_CBT | 5 | ウィンドウの変更やフォーカス設定などのメッセージ | スレッドまたはシステム |
WH_DEBUG | 9 | 他のフックのフックを実行するかどうか | スレッドまたはシステム |
WH_FOREGROUNDIDLE | 11 | フォアグラウンド プログラムはアイドル状態です | スレッドまたはシステム |
WH_GETMESSAGE | 3 | メッセージキューに投稿されたメッセージ | スレッドまたはシステム |
WH_ジャーナルの再生 | 1 | 録音されたメッセージを再生する | システム |
WH_JOURNALRECORD | 0 | 入力メッセージを監視およびログに記録する | システム |
WH_キーボード | 2 | キーボードメッセージ | スレッドまたはシステム |
WH_マウス | 7 | マウスメッセージ | スレッドまたはシステム |
WH_MSGFILTER | -1 | メニューのスクロールバー、ダイアログメッセージ | スレッドまたはシステム |
WH_SHELL | 10 | シェルメッセージ | スレッドまたはシステム |
WH_SYSMSGFILTER | 6 | メニューのスクロール バー、すべてのスレッドのダイアログ メッセージ | システム |
2. VB プログラミングでのフックの実装
(1) フック関数(HOOK関数)の形式。フック関数が実際には関数である場合、関数はダイナミック リンク ライブラリに配置される必要があります。この関数には特定のパラメータ形式があり、VB では次のようになります。
プライベート関数 HookFunc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long |
その中で、nCode はフックが生成される状況を表し、フックに応じて可能な値のセットが異なります。パラメータ wParam および lParam の戻り値には、監視対象のメッセージの内容が含まれます。フックが監視するメッセージの種類は、nCode の値によって異なります。 VB で設定されたフック関数の一般的なフレームワーク形式は次のとおりです。
プライベート関数 HookFunc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long nCodeのケースを選択 case ncode<0:hookfunc=callnexthookex(hHookFunc, nCode, wParam, lParam) ケース値 1: 処理 1: HookFunc=X1 case2:処理工程2:HookFunc=X1 … エンドセレクト 関数の終了 |
関数の戻り値。メッセージを処理する場合は 0 を渡し、それ以外の場合は 1 を渡してメッセージを受け取ります。
(2) フックのインストールと実行。フックのインストールには、いくつかの API 関数が使用されます。 API 関数 SetWindowsHookEx() を使用して、アプリケーション定義のフック サブルーチンをフック リストにインストールできます。 SetWindowsHookEx() 関数の宣言は次のとおりです。
関数 SetWindowsHookEx Lib user32 Alias を宣言 SetWindowsHookExA(ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long |
idHook 値は処理するメッセージ タイプであり、lpfn 値はフック サブルーチンのアドレス ポインタです。 dwThreadId パラメータが 0 であるか、別のプロセスによって作成されたスレッドの識別子の場合、lpfn は DLL 内のフック サブルーチンを指す必要があります。さらに、lpfn は現在のプロセスのフック サブルーチン コードを指すことができます。 hMod 値はアプリケーションのハンドルで、lpfn が指すサブルーチンを含む DLL を識別します。 dwThreadId が現在のプロセスによって作成されたスレッドを識別し、サブルーチン コードが現在のプロセスにある場合、hMod は 0 でなければなりません。 dwThreadId 値は、インストールされたフック サブプロセスに関連付けられたスレッドの識別子です。0 の場合、フック サブプロセスはすべてのスレッドに関連付けられます。フックが正常にインストールされた場合は、フック サブプロセスのハンドルが返され、失敗した場合は 0 が返されます。
さらに、CallNextHookEx() 関数は通常、フック サブルーチンで呼び出されて、フック リストで指定された次のフック サブルーチンを実行する必要があります。そうしないと、他のフックがインストールされているアプリケーションはフック通知を受信せず、結果が正しくなくなります。 CallNextHookEx() 関数の宣言は次のとおりです。
関数 CallNextHookEx Libuser32 エイリアスを宣言 CallNextHookEx(ByVal hHook As Long, ByVal ncode As Lonog, ByVal wParam As Long, lParam As Any) As Long |
hHook 値は SetWindowsHookEx() の戻り値であり、nCode、wParam、および lParam は Hook 関数の 3 つのパラメーターです。プログラムが終了する前に、UnhookWindowsHookEx() 関数を呼び出して、フックに関連付けられたシステム リソースを解放する必要があります。 UnhookWindowsEx() 関数は次のように宣言されます。
関数の宣言 WindowsHookEx Lib user32 Alias Unhook WindowsHookEx(ByVal hhook As Long)As Long |
hHook はフックをインストールするときの戻り値、つまりフックのサブプロセスのハンドルです。
(3) VB にフックをインストールする際に注意すべき問題。 lpfn パラメータは HookFunc のアドレスです。VB では、HookFunc コードを標準の .BAS モジュールに配置し、Address Of HookFunc として渡す必要があると規定しています。 RemoteHook の場合、HookFunc をダイナミック リンク ライブラリに含める必要があるため、RemoteHook を VB で使用する場合は、GetModuleHandle() と GetProcAddress() という 2 つの API 関数も使用されます。これらの宣言は次のとおりです。
関数 GetModuleHandle Libkernel32 エイリアス GetModuleHandleA(ByVal lpModuleName As String) As Long を宣言します 関数 GetProcAddress Lib kernel32 Alias を宣言 GetProcAddress(ByVal hModule As Long, ByVal lpProcName As String) As Long |
hmod 値は、フック プロセスを含むモジュール名ハンドルです。LocalHook の場合、値は Null (VB では 0 が渡されます)、RemoteHook の場合、GetModuleHandle (name.dll) を使用して渡すことができます。 。