読者です 読者をやめる 読者になる 読者になる

Log.i53

Themidaのアンパックを目指すブログ改め使い物になるえんじにゃを目指すブログ

AntiDebug技術:Process Injection

 パッカーによってはプロセスインジェクションを機能としてもつものが存在します。この機能では、アンパッキングスタブが選択されたホストプロセス(それ自身, explorer.exe, iexplorer.exeなど)を生成して、アンパックされた実行ファイルがそのホストプロセスにインジェクトされます。
f:id:i53:20150609032610p:plain

 以下は、プロセスインジェクションをサポートするパッカーのスクリーンショットです。
f:id:i53:20150609032621p:plain

 このパッカーの機能を利用して外部ネットワークコネクションの実行が許可されているプロセスに悪意あるコードを埋め込むことでファイアウォールのバイパスが可能となります。

 パッカーがプロセスインジェクションを実行する上で用いる手法の1つを以下に示します:

  1. サスペンドされた子プロセスとしてホストプロセスを生成する. これはCREATE_SUSPENDEDプロセス生成フラグでkernel32!CreateProcess()を使用することで生成できる. この時点で初期スレッドがサスペンドされた状態で生成され、DLLはローダールーチン(ntdll!LrdInitializeThunk)がまだ呼び出されていないのでDLLはロードされていない状態となっている. このスレッドのコンテキストはPEBアドレスやホストプロセスのエントリポイントなどを含むレジスタ値でセットアップされる.
  2. kernel32!GetThreadContext()を使用して、子プロセスの初期スレッドのコンテキストを取得する.
  3. CONTEXT.EBXから子プロセスのPEBアドレスを取得する.
  4. PEB.ImageBase(PEB+0x8)から子プロセスのイメージベースを取得する.
  5. ntdll!NtUnmapViewOfSection()のBaseAddressおあらメータに取得したイメージベースを与えて呼び出すことで、子プロセス内のオリジナルホストイメージがアンマップされる.
  6. アンパッキングスタブはkernel32!VirtualAllocEx()のdwSizeパラメータにアンパックされた実行ファイルのイメージサイズを与えて呼び出すことで、子プロセス内部にメモリを割り当てる.
  7. kernel32!WirteProcessMemory()を使用して、アンパックされた実行ファイルのPEヘッダと各セクションが子プロセスに書き込まれる.
  8. 子プロセスのPEB.ImageBaseがアンパックされた実行ファイルのイメージベースと一致するように更新される.
  9. kernel32!SetThreadContext()により子プロセスの初期スレッドのコンテキストが更新される.この時CONTEXT.EAXがアンパックされた実行ファイルのエントリポイントに設定される.
  10. kernel32!ResumeThread()によって子プロセスの実行を再開する.

 生成された子プロセスのデバッグをそのエントリポイントから開始するには、WriteProcessMemory()にブレークポイントを設定して、エントリポイントを含むセクションが子プロセスに書き込まれた時に、エントリポイントコードを"jump to self"命令(0xEB 0xFE)でパッチする必要があります。子プロセスのメインスレッドが一時停止した時、先ほどのパッチにより子プロセスはそのエントリポイントで無限ループに陥ります。あとは子プロセスにデバッガをアタッチして、パッチした命令を元の命令に戻して通常のデバッグを再開します。