OrangeMaker_logo
memo アイコン SDK-MFC 備忘録

Windows SDKやMFCに関するメモです。
(記載内容について正しいことを保証するものではありません。MSDN等で確認してください)

DLLインジェクションメモ

2010/11/25 作成

DLLインジェクションというのは、DLLを別プロセスに挿入させるテクニックで、使用方法によっては有益なツールや悪意のあるツールまで様々な使用方法があります。
ポイントは、プロセス空間にはいってしまうので通常はプロセス外から取得できな情報取得や操作ができる点です。
通常はDLLをプロセスに挿入しただけでは、大したことはできないのですが、これにメッセージフックやAPIフックなどを組み合わせると強力なテクニックになります。
こういった、テクニックはシステム系のツールなどでよくつかわれているようです。
例えば、ウイルスバスターなどのアンチウイルスソフト等もこういった方法で起動プロセスの抑止や、通信内容のスキャンを行っていいるものと思われます。(仔細に調べた訳ではないですが。。)

一般によく知られている、インジェクション方法は、レジストリに登録する方法とグローバルメッセージフックを使用する方法があります。

-方法 その1
以下のレジストリにDLLへのパスを登録します。

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

ここに、登録したDLLをロードするのはUSER32.DLLが行います。
USER32.DLLがロードするということはUSER32.DLLがインポートされていないプロセスはインジェクションされないという理屈ですがUSER32.DLLはWindowsの中核のDLなので大抵のプロセスで使用されています。   この方法の困った点は、インジェクションを解除できない点です。
この方法でロードされたDLLはプロセスを終了するまでその状態を変えることはできません。
プロセスをすべて終了させるというわけにはいかないので、結局、DLLを差し替える為には一旦シャットダウンまで行う必要があります。
実際に、レジストリエディタなどで調べればわかりますが、通常はこのエントリは空っぽです。(当方の所持しているPCで調査した限り。。)
逆に、ここに不審なDLLが登録されている場合は出所を調査してみた方がいいのかもしれません。(笑)

-方法 その2
もう一つの方法は、グローバルメッセージフックの副作用(SideEffect)として、DLLインジェクションを行う方法です。
DLLインジェクションの方法としては、こちらの方法の方がよくつかわれているようです。
このままメッセージフックとの組み合わせでイベントロガーなどが比較的簡単にできてしまいます。
この方法のメリットは、インジェクトしたDLLのアンロードが制御できる点です。
APIとしては、

	HHOOK SetWindowsHookEx(
  			int idHook,        // フックタイプ
  			HOOKPROC lpfn,     // フックプロシージャ
  			HINSTANCE hMod,    // アプリケーションインスタンスのハンドル
  			DWORD dwThreadId   // スレッドの識別子
	);
	

フックタイプは16種類ほど定義されていて、フックタイプによってコールバックプロシージャが異なります。
(詳細はMSDNの記載を参照してください。)

フックプロシージャはインジェクションだけが目的の場合ダミーでもいいのですが、
その場合でも、必ずCallNextHookEx()を呼び出してフックチェーンをつないでおく必要があります。

hModは、DLLのモジュールハンドルを渡します。このハンドルは自分でDLLをロードしてハンドルを取得してもいいですが、簡単なのはインジェクション対象のDLLをインポートしておいてDLLMain()でモジュールハンドルをグローバル変数にしておいて、Export関数でSetWindowEx()を呼び出しこの時にグローバル変数に格納しておいたモジュールハンドル(インスタンスハンドル)を参照する方法です。(大抵のサンプルはこうなってました。)

スレッドの識別子に0(NULL)を設定すれば、グローバルフックになります。(スレッド識別子に具体的なスレッドを使用するとローカルフックになります。)
注意点は、このAPIを呼び出した瞬間にすべてのプロセスにDLLがインジェクションされるわけでなく、何らかのメッセージトリガが必要になります。
※どのメッセージがトリガになるかはどうもフックタイプによって異なるような感じです。

フックの解除(インジェクションの解除)は、SetWindowHookEx()の戻り値を引数にUnHookWindowHookEx()を呼び出します。

	BOOL UnhookWindowsHookEx(
		HHOOK hhk   // 削除対象のフックプロシージャのハンドル
	);
	

具体的な、インジェクションを行うプログラムを書くためにはほかに、排他制御や共有メモリなどの知識が必要となります。