Cmd and Conquer: Flare-qdb による De-DOSfuscation

Daniel Bohannon が優れたDOSfuscationに関する論文を発表したとき、私はシステム エンジニアとして使用したトリックが、攻撃者が検出を回避するのにどのように役立つかを知り、魅了されました。 FLARE マルウェア キューでの仕事の一環として、恐ろしく難読化されたバッチ ファイルを分析しなければならなくなるまで、私はこの会話にあまり貢献することができませんでした。

以前、Vivisect に基づくコマンドラインおよび Python スクリプト可能なデバッガーであるFlare-qdbをリリースしました。以前、flare-qdb を使用してマルウェアの動作を計測および変更する方法について書きました。 Flare-qdb は Austin Baker と Jacob Christie のSANS DFIR Summit 2017 ブリーフィングにもゲスト出演し、Windows イベント ログ サービスにプロセス作成イベントを除外させました。このブログ投稿では、flare-qdb を使用して「スクリプト ブロックのログ記録」を Windows コマンド インタープリターにもたらす方法を紹介します。また、cmd.exe のプロセス アドレス空間で 1 ビットだけ反転して見つけたイースター エッグも共有します。最後に、 flare-qdb に追加したスクリプトを共有します。これにより、悪意のあるコマンド スクリプトを自分で実行して (もちろん安全な環境で) 難読化を解除できます。しかし、最初に、このソリューションに至った分析について説明します。

一目見ただけで

図 1 は、Daniel Bohannon の論文で参照されている BatchEncryption ツールを使用して難読化されたバッチ スクリプト (MD5 ハッシュ 6C8129086ECB5CF2874DA7E0C855F2F6) を示しています。このファイルは、この記事の執筆時点では VirusTotal には表示されませんが、そのドロッパーには表示されます (MD5 ハッシュは ABD0A49FDA67547639EEACED7955A01A です)。私の目標は、このスクリプトの難読化を解除し、攻撃者が何をしていたかを報告することでした。

Contents of XYNT.bat
XYNT.bat の内容

この 165k のバッチ ファイルは C:WindowsTempXYNT.bat としてドロップされ、そのドロッパーによって実行されます。そのコマンドは、環境変数の部分文字列から構築されます。図 2 は、ECHO コマンドを使用して最初のコマンドをデコードする方法を示しています。

ECHO コマンドによる部分的なコマンドのデコード
ECHO コマンドによる部分的なコマンドのデコード

このスクリプトは、何百ものコマンドを使用して環境変数を設定し、最終的に展開して悪意のあるコマンドの難読化を解除します。このスクリプトの難読化を解除するための面倒な方法は、難読化が解除された各コマンドをコンソールに出力する ECHO ステートメントを先頭に追加して、各コマンドのファングを解除することです。残念ながら、ECHO コマンドは各コマンドを「デコード」できますが、BatchEncryption では、以降のコマンドをデコードするために SET コマンドを実行する必要があります。悪意のある機能を完全に期待どおりに実行しながらこのスクリプトをデコードするには、難読化された数百の SET コマンドを繰り返し慎重にエコーし、選択的に実行する必要があります。

BatchEncryption の皮肉なことに、バッチ スクリプトは難読化の解除が容易であると見なされており、バイナリ コードはネットワーク防御者の詮索好きな目からロジックを隠すためのより安全な場所になっています。しかし、BatchEncryption は、元のコマンドを再構築するために環境変数を広範かつ階層的に使用することで、分析に手ごわい障壁を追加します。

状況を把握する

自分でスクリプトの難読化を解除するよりも、コマンドをログに記録するように cmd.exe をインストルメント化する方が簡単かどうかを確認することにしました。まず、cmd.exe をデバッグし、CreateProcessW にブレークポイントを設定して、コマンド プロンプトからプログラムを実行しました。図 3 は、cmd.exe がメモ帳を実行するときの CreateProcessW のコール スタックを示しています。

cmd exe での CreateProcessW のコール スタック
cmd.exe の CreateProcessW のコール スタック

cmd!ExecPgm から始めて、cmd.exe 内の上記の関数の逆アセンブリを確認し、コマンド文字列の起源をコール スタックまで追跡しました。 cmd!Dispatch を発見しました。これは、文字列ではなく、コマンド、引数、および I/O リダイレクト情報 (プログラムの標準出力またはエラー ストリームをファイルまたはデバイスにリダイレクトするなど) へのポインターを含む構造体を受け取ります。テストの結果、これらの文字列にはすべての環境変数が展開されていることが明らかになりました。つまり、難読化が解除されたコマンドをここから読み取ることができるはずです。

図 4 は、コマンド「echo hai > nul」を実行した後の WinDbg でのこの構造の探索です。このコマンドは単語 hai を標準出力ストリームに出力しますが、右山かっこを使用して標準出力を NUL デバイスにリダイレクトし、すべてのデータを破棄します。オレンジ色のボックスは、分析中に注意を引いた null 以外のポインターを強調表示し、矢印は、その内容を発見するために使用したコマンドを指しています。

cmd!Dispatch の 2 番目の引数で興味深いポインタを調べる
cmd!Dispatch の 2 番目の引数で興味深いポインタを調べる

ユーザーは 1 つのコマンドで複数の I/O ストリームをリダイレクトできるため、cmd.exe はリンクされたリストで I/O リダイレクトを表します。たとえば、リスト 1 のコマンドは、標準出力 (ストリーム #1 は暗黙的) を shares.txt にリダイレクトし、標準エラー (ストリーム #2 は明示的に参照) を errors.txt にリダイレクトすることを示しています。

ネット使用 > 共有.txt 2>errors.txt

リスト 1: コマンドライン I/O リダイレクトの例

図 5 に、コマンド データ構造と I/O リダイレクション リンク リストをブロック図形式で示します。

コマンドデータ構造図
コマンドデータ構造図

調べてみると、cmd!Dispatch はシェルの組み込みプログラムと実行可能プログラムの両方の実行を担当しているため、CreateProcess での中断とは異なり、プロセスの作成に至らないコマンドを見逃すことはありません。これらの調査結果に基づいて、コマンドの実行時にコマンドを解析およびダンプするための Flare-qdb スクリプトを作成しました。

De-DOSfuscator の紹介

De-DOSfuscator は、flare-qdb と Vivisect を使用して、cmd.exe の Dispatch 関数をフックし、メモリからコマンドを解析します。 De-DOSfuscator スクリプトは、64 ビットの Python 2 インタープリターで実行され、コンソールとログ ファイルの両方にコマンドをダンプします。このスクリプトは、 flare-qdbの最新バージョンに付属しており、dedosfuscator.exe という名前の Python エントリ ポイントとしてインストールされます。

De-DOSfuscator は、エクスポートされていない Dispatch 関数の場所に依存してコマンドを記録しますが、その場所はシステムごとに異なります。便宜上、インターネット接続が利用可能な場合、De-DOSfuscator は Microsoft のシンボル サーバーを使用してこの関数のオフセットを自動的に取得します。オフラインで使用できるようにするには、オフライン マシンから cmd.exe のコピーへのパスを –getoff スイッチに指定して、このオフセットを取得します。次に、その出力をオフライン マシンの –useoff スイッチの引数として指定して、機能がどこにあるかを De-DOSfuscator に通知できます。または、ダウンロードした PDB または正しいシンボルを含むローカル シンボル キャッシュで De-DOSfuscator を使用することもできます。

図 6 は、1 つのセッションでオフセットを取得して使用する方法を示しています。これを分離された VM で機能させるには、その VM に固有のゲストのコマンド インタープリターのコピーへのパスを代わりに指定することに注意してください。

オフセットの取得と使用、および De-DOSfuscator のテスト
オフセットの取得と使用、および De-DOSfuscator のテスト

これは、図 1 の BatchEncrypted スクリプトでうまく機能します。見てみましょう。

結果

図 7 は、XYNT.bat の実行後に De-DOSfuscator によって作成されたログを示しています。数百行の SET ステートメントが、さらにコマンドを作成するための環境変数を徐々に作成します。 endlocal コマンドライン拡張キーワードのスペルミスにも注意が必要です。

ダンプされたコマンドの先頭
ダンプされたコマンドの先頭

これらの環境変数操作は、図 8 に示すように実際のコマンドに取って代わられます。スクリプトの最初のアクションの 1 つは、reg.exe を使用して NUMBER_OF_PROCESSORS 環境変数をチェックすることです。この分析システムには 1 つの vCPU しかありませんでした。これは、620 行目の set “a=1” 出力で確認できます。この後、スクリプトは goto del を実行し、最終的にスクリプトとその他のドロップされたファイルを削除するバッチ ラベルに分岐します。

サンドボックス対策
サンドボックス対策

これは、一般的なサンドボックスの回避方法をバッチ指向でアレンジしたものです。これが機能するのは、多くのマルウェア分析サンドボックスが単一の CPU で実行され、ハイパーバイザーのリソースを最小限に抑えるのに対し、最新のシステムのほとんどは少なくとも 2 つの CPU コアを備えているためです。スクリプトのコマンドを簡単に読み取ることができるようになったので、たとえば VM で使用できる vCPU の数を増やすことで、この回避を簡単に回避できます。図 9 は、残りのコードを実行するよう誘導した後の De-DOSfuscator のログを示しています。

サンドボックス対策回避後
サンドボックス対策回避後

XYNT.bat は、ドロップされたバイナリを呼び出して、永続化のために Windows サービスを作成および開始します。ドロップされた最大のバイナリは XMRig 暗号通貨マイナーの亜種であり、スクリプトが参照するサービスと実行可能ファイルの多くも暗号通貨に関連しているようです。

イースター、おめでとう

イースターはまだ先ですが、とても素敵な小さな発見なので、とても早い段階でイースターエッグを紹介しなければなりません。 cmd.exe を調べているときに、fDumpParse という名前の変数に、興味深い動作を制御しているように見える相互参照が 1 つしかないことに気付きました。唯一の相互参照と関連するコードを図 10 に示します。fDumpParse は、コード内の他の場所ではアクセスできませんが、解析されたコマンドに関する情報をダンプするために関数を呼び出すかどうかを制御します。

fDumpParse の評価と相互参照 (EDI は NULL)
fDumpParse の評価と相互参照 (EDI は NULL)

これを試すには、De-DOSfuscator の –fDumpParse スイッチを使用できます。次に、解析した内容がより明確なコマンド プロンプトが表示されます。図 11 は、解析されたコマンド トークンの抽象構文ツリー (AST) のグラフィカル表現と共に例を示しています。

fDumpParse が設定されたコマンド インタープリター
fDumpParse が設定されたコマンド インタープリター

Microsoft はおそらく、開発者が cmd.exe の問題をデバッグできるように fDumpParse フラグを挿入しました。残念ながら、これは気の利いたものですが、一括難読化解除には欠点があります。

  • この出力は、通常のコマンドよりも読みにくいものです。これは、入力された順序ではなく、事前の順序でツリーをダンプするためです。
  • コンソールからコピーされた出力には、コンソール ホスト プログラムのテキスト ラッピング動作によっては、不要な改行が含まれる場合があります。
  • コマンド インタープリターをスクロールして出力を読み取ったりコピーしたりするのは面倒です。
  • コンソール バッファは限られているため、すべてがキャプチャされるわけではありません。
  • 悪意のあるスクリプト作成者は、引き続き CLS コマンドを使用して画面をクリアし、すべての fDumpParse 出力を非表示にすることができます。
  • コマンド セパレーター (XYNT.bat にある) を使用してコマンドを勝手に結合すると、図 12 に示すように、コンソールの幅を超えてラップ アラウンドする読み取り不能な AST が生成されます。
fDumpParse の結果がコンソールの幅を超えています
fDumpParse の結果がコンソールの幅を超えています

したがって、fDumpParse は、悪意のある大規模なバッチ ファイルの難読化解除には適していません。ただし、短いスクリプトや 1 回限りのコマンドの難読化を解除するためには、依然として興味深いものであり、有用です。通常の操作と同様に、–getoff を介してオフラインで使用するために De-DOSfuscator が必要とするオフセットを取得し、–useoff を介して使用することができます。

まとめ

高度に難読化されたコマンド スクリプトの例を示し、難読化を解除するための便利なツールと、それを合成するために従った分析手順を共有しました。 De-DOSfuscator スクリプト コードは、 flare-qdb の最新バージョンに付属しており、flare-qdbをインストールするときにスクリプト エントリ ポイント (dedosfuscator.exe) としてアクセスできます。これが、悪意のあるバッチ スクリプトを便利に分析するのに役立つだけでなく、マルウェアに対して Flare-qdb を使用する独自の創造的な方法を考案するきっかけにもなることを願っています。

参照: https://www.mandiant.com/resources/blog/cmd-and-conquer-de-dosfuscation-flare-qdb

コメント

タイトルとURLをコピーしました