「フック(フッキング)」とは、ソフトウェア/コンポーネント間で渡されるWindows API関数などの呼び出し、メッセージ、またはイベントをインターセプト(傍受)することにより、オペレーティングシステム、アプリケーション、または他のソフトウェア部品の動作を変更または拡張するための方法です。
DDetoursは、関数にフックを挿入、あるいは関数からフックを削除可能なライブラリで、Windows 32ビット/64ビットの両方のアーキテクチャをサポートしています。このライブラリの基本的な考え方は、インターセプトされた関数への無条件ジャンプ命令を挿入することで、ターゲット関数のプロローグを置換することです。
フッキングのルール
DDetoursライブラリを利用して正しくフッキングを実行するには、以下のルールに従う必要があります。
- インターセプトプロシージャは、元のプロシージャと同じシグネチャを持っていなければなりません。つまり、同じパラメータ(型)と同じ呼び出し規則でなければなりません。
- Delphiオブジェクト/ COMオブジェクトをフックする場合、InterceptProc/Trampolineの最初のパラメータは、そのオブジェクトへのポインタ(Self)である必要があります。
- マルチフックを行う場合、各フックにはNextHook/Trampoline関数が必要です。
- マルチスレッドアプリケーションを構築する場合、フックの挿入/削除はBeginTransaction/EndTransactionフレーム内で実行する必要があります。
- インターセプト関数内で元の関数を直接呼び出そうとすると、再帰的に呼び出される可能性がありますので、このような利用は絶対に避けてください。常にNextHook/Trampoline 関数を使用するようにしてください。
- 元の関数を内部的に呼び出す可能性のある関数を呼び出す場合は、EnterRecursiveSection / ExitRecursiveSectionを使用してください。
DDetoursライブラリを利用したサンプルコードは、以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
type TMessageBox = function(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall; var TrampolineMessageBox: TMessageBox = nil; function InterceptMessageBox(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall; var Self: TMain; begin Self := GetTrampolineParam(TrampolineMessageBox); Self.Caption := 'MessageBox hooked !'; Result := TrampolineMessageBox(hWnd, 'this text was hooked', 'this title was hooked', MB_ICONWARNING); end; procedure TMain.FormCreate(Sender: TObject); begin BtnUnHook.Enabled := False; end; procedure TMain.BtnHookClick(Sender: TObject); begin TrampolineMessageBox := InterceptCreate(@MessageBox, @InterceptMessageBox, Self); BtnUnHook.Enabled := True; BtnHook.Enabled := False; end; procedure TMain.BtnMsgBoxClick(Sender: TObject); begin MessageBox(0, 'text', 'caption', 0); end; procedure TMain.BtnUnHookClick(Sender: TObject); begin if Assigned(TrampolineMessageBox) then begin InterceptRemove(@TrampolineMessageBox); TrampolineMessageBox := nil; BtnHook.Enabled := True; BtnUnHook.Enabled := False; end; end; initialization finalization if Assigned(TrampolineMessageBox) then InterceptRemove(@TrampolineMessageBox); |
DDetoursライブラリは、無償で利用可能なオープンソースですが、Mozilla Public License 2.0として規定されています。このライブラリはGitHub経由でこちらから入手できます。なお、エンバカデロではこのライブラリに関するテクニカルサポートサービスは提供しておりません。
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition