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