Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
DelphiRAD Studio

DDetoursライブラリを利用してWindowsアプリケーションを迅速かつ簡単にフックする

hook-delphi-and-windows-api-functions-with-ddetours-ja

「フック(フッキング)」とは、ソフトウェア/コンポーネント間で渡されるWindows API関数などの呼び出し、メッセージ、またはイベントをインターセプト(傍受)することにより、オペレーティングシステム、アプリケーション、または他のソフトウェア部品の動作を変更または拡張するための方法です。

DDetoursは、関数にフックを挿入、あるいは関数からフックを削除可能なライブラリで、Windows 32ビット/64ビットの両方のアーキテクチャをサポートしています。このライブラリの基本的な考え方は、インターセプトされた関数への無条件ジャンプ命令を挿入することで、ターゲット関数のプロローグを置換することです。

フッキングのルール

DDetoursライブラリを利用して正しくフッキングを実行するには、以下のルールに従う必要があります。

  • インターセプトプロシージャは、元のプロシージャと同じシグネチャを持っていなければなりません。つまり、同じパラメータ(型)と同じ呼び出し規則でなければなりません。
  • Delphiオブジェクト/ COMオブジェクトをフックする場合、InterceptProc/Trampolineの最初のパラメータは、そのオブジェクトへのポインタ(Self)である必要があります。
  • マルチフックを行う場合、各フックにはNextHook/Trampoline関数が必要です。
  • マルチスレッドアプリケーションを構築する場合、フックの挿入/削除はBeginTransaction/EndTransactionフレーム内で実行する必要があります。
  • インターセプト関数内で元の関数を直接呼び出そうとすると、再帰的に呼び出される可能性がありますので、このような利用は絶対に避けてください。常にNextHook/Trampoline 関数を使用するようにしてください。
  • 元の関数を内部的に呼び出す可能性のある関数を呼び出す場合は、EnterRecursiveSection / ExitRecursiveSectionを使用してください。

DDetoursライブラリを利用したサンプルコードは、以下の通りです。

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経由でこちらから入手できます。なお、エンバカデロではこのライブラリに関するテクニカルサポートサービスは提供しておりません。

Kai for RAD Studio is Now Available! Special Live Webinar: Introducing Kai - A New Chapter for RAD Studio RAD Studio 13.1 Florence Now Available

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES