DbgNexum: WindowsデバッグAPIを用いたシェルコード注入

DbgNexum は、Windows デバッグAPIと共有メモリ(ファイルマッピング)を使用してシェルコードを注入するための概念実証(PoC)です。リモートメモリへの直接の書き込み・読み取りを回避し、代わりにコンテキスト操作によってターゲットプロセス自身にペイロードを読み込み・実行させます。

インジェクタはターゲットプロセスにアタッチし、サスペンド状態のスレッドを作成します。デバッグループを通じて、特定のリターンアドレスで実行を捕捉するためにハードウェアブレークポイントを設定します。捕捉のたびに、インジェクタはCPUレジスタを変更して関数呼び出しを模倣し、ターゲットプロセス内で一連のWindows API関数呼び出しを組み立てて実行します。

機能

  • WriteProcessMemory / VirtualAllocEx 不要: ペイロードは CreateFileMapping と MapViewOfFile を介して転送されます。
  • ReadProcessMemory 不要: この手法は、必要な主要情報をすべてスレッドコンテキストから取得します。

仕組み

実行フローは、インジェクタのデバッグループとターゲットプロセスの間を絶えず行き来します。

注入ステージ

DebugLoop 関数には主要な注入ロジックが含まれており、「ステートマシン」をオーケストレーションします:

0. 準備:

  • インジェクタは現在のスタックポインタを保存し、各ステージで再利用します
  • 固定したスタックのリターンアドレスを取得するため、トラップフラグを設定し、実行を即時の ret 呼び出しへ向けます。

1. 割り当て:

  • 固定したスタックのリターンアドレスにHWBPを設定し、呼び出した関数がリターンしたときに通知を受け取れるようにします。
  • スレッドを準備し、(当然ながら)小さなバッファを確保するために LocalAlloc を呼び出すよう強制します。

2. データ設定:

  • スレッドを準備し、文字列 MZ を先に割り当てたバッファへコピーするために memcpy を呼び出すよう強制します。

3. スタック準備:

  • スレッドに memset を呼び出させ、スタックスロットをゼロクリアします。これはステージ5の準備で、そこで MapViewOfFile を呼び出します。この関数は4個を超える引数を使用するため、第5引数はスタック経由で渡されます(ここで設定します)。

4. マッピングを開く:

  • ステージ2と3で「作成」した MZ という名前を使って OpenFileMappingA を呼び出すようスレッドに強制します。

5. ペイロードをマップ:

  • ターゲットに MapViewOfFile を呼び出させます。これにより、共有メモリセクション(シェルコードを含む)が EXECUTE 権限付きでターゲットのアドレス空間にマップされます。

6. 実行:

  • MapViewOfFile が返したアドレスへ RIP をリダイレクトします。
  • デバッグレジスタをクリアしてデタッチします。

ダウンロード&使用

翻訳元: https://meterpreter.org/dbgnexum-shellcode-injection-using-the-windows-debugging-api/

ソース: meterpreter.org