
完全動的コールスタックスプーファーのPoC実装
SilentMoonwalkは、完全動的コールスタックスプーファーのPoC実装であり、呼び出し元をコールスタックから除去し、ROPを使用してアンワインドと制御フローを非同期化する技術を実装しています。
このPoCは、スタックスプーフィングに関する共同研究の成果です。研究の著者は以下の通りです。
この研究は、Waldo-IRCとTrickster0の貢献なしには不可能でした。両者はPoCの初期段階とその背後にある研究に多大な貢献をしました。
このリポジトリは、任意のWindows APIを呼び出す際にコールスタックをスプーフィングするPoC実装を示しています。
この試みは、こちらのTwitterスレッドおよびこちらのTwitterスレッドに触発されました。そこでは、師であるnamazsoが、ROPチェーンを用いてアンワインドと実際の制御フローを非同期化し、その後元のスタックを復元するスタックアンワインド手法の拡張を示し、提案しました。
このPoCは上記と同様のことを試み、非同期化スタックを使用して元のコールスタックを完全に隠し、EXEイメージベースもそこから除去します。戻り時にはROPガジェットが呼び出され、元のスタックを復元します。コード内では、このプロセスをループ内で10回繰り返し、毎回異なるフレームを使用して安定性を証明しています。
現在、このツールは2つのモードをサポートしています。そのうちの1つは、機能しないPOP RBPフレームに対する不適切なパッチであり、現在のRSPをシフトし、コールスタックに2つの偽のフレームを追加することで動作します。合成フレームを使用して動作するため、このモードを「SYNTHETIC」と呼んでいます。
RBPレジスタをスタックからポップすることでアンワインドするフレームを選択すると、ツールが不適切なフレームを選択し、以下のように不自然に途切れたコールスタックになる可能性があります。

この問題に対する愚直な解決策は、2つの偽のフレームを作成し、それらを途切れたコールスタックにリンクすることです。これにより、一見正当に見えるコールスタックが作成されます(たとえPOP RBPを呼び出す適切なフレームがなくても)。しかし:
_合成スプーフィングの結果は以下の画像で確認できます。

図1: Windows 10 - 一見正当でアンワインド不可能なコールスタック。EXEモジュールが完全に除去されています(引数なしの関数getcharを呼び出し)
注: この動作モードはデフォルトで無効になっています。有効にするには、CALLSTACK_TYPEを1に変更してください。
このモードは上記の問題に対する正しい解決策であり、不適切なフレームを適切なフレームに置き換えるだけです。

図2: Windows 10 - 正当でアンワインド可能なコールスタック。EXEモジュールが完全に除去されています(4つの引数を持つ関数MessageBoxAを呼び出し)
リポジトリには、ランタイム関数を検査するための小さなユーティリティも含まれています。これはランタイム関数エントリの解析に役立つかもしれません。
UnwindInspector.exe -h
Unwind Inspector v0.100000
必須引数:
-m <module>: ターゲットDLL
-f <function>: ターゲット関数
-a <function-address>: ターゲット関数アドレス
出力例:
UnwindInspector.exe -m kernelbase -a 0x7FFAAE12182C
[*] 関数アドレス 0x7ffaae12182c を使用
ランタイム関数 (0x000000000000182C, 0x00000000000019ED)
アンワインド情報アドレス: 0x000000000026AA88
バージョン: 0
バージョン+フラグ: 00000000
プロローグサイズ: 0x1f
コード数: 0xc
フレームレジスタ: 0x0
フレームオフセット: 0x0
アンワインドコード:
[00h] フレーム: 0x741f - 0x04 - UWOP_SAVE_NONVOL (RDI, 0x001f)
[01h] フレーム: 0x0015 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0015)
[02h] フレーム: 0x641f - 0x04 - UWOP_SAVE_NONVOL (RSI, 0x001f)
[03h] フレーム: 0x0014 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0014)
[04h] フレーム: 0x341f - 0x04 - UWOP_SAVE_NONVOL (RBX, 0x001f)
[05h] フレーム: 0x0012 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0012)
[06h] フレーム: 0xb21f - 0x02 - UWOP_ALLOC_SMALL (R11, 0x001f)
[07h] フレーム: 0xf018 - 0x00 - UWOP_PUSH_NONVOL (R15, 0x0018)
[08h] フレーム: 0xe016 - 0x00 - UWOP_PUSH_NONVOL (R14, 0x0016)
[09h] フレーム: 0xd014 - 0x00 - UWOP_PUSH_NONVOL (R13, 0x0014)
[0ah] フレーム: 0xc012 - 0x00 - UWOP_PUSH_NONVOL (R12, 0x0012)
[0bh] フレーム: 0x5010 - 0x00 - UWOP_PUSH_NONVOL (RBP, 0x0010)
PoCをビルドし、画像と同様の動作を確認するには、以下の設定を確認してください。
/GS-)/Od)/GLを削除)/Os、/Otを削除)/Oi)このトピックに関する先行研究に言及しておきます。これらは本研究成果の基盤を築きました。