Vidarが独自バイトコードインタープリタとARXストリーム暗号でビルドごとに文字列を難読化

情報窃取型マルウェア「Vidar」に、埋め込み文字列を隠すための軽量な独自仮想マシンと、ビルドごとに変化するストリーム暗号の実装が導入されました。これにより、静的検知や自動リバースエンジニアリングのコストが押し上げられています。

2018年に初めて確認されたVidarは、現在も広く追跡されている認証情報窃取型マルウェアファミリーです。

運営者はマルウェア本来の目的――ブラウザデータ、暗号資産ウォレット情報、認証情報などの被害者から得られる貴重な資産を窃取すること――を変えることなく、内部の防御機構を絶えず改変し続けています。

今回の変更が重要な意味を持つのは、防御側が従来頼りにしてきた大きな分析上の強み、つまりAPI名、エラーメッセージ、設定項目、ブラウザのターゲット情報、HTTPヘッダー、C2(コマンド&コントロール)関連の痕跡といった、読み取り可能な埋め込み文字列を狙い撃ちにしているためです。

ThreatLabzは調査対象のバージョンをVidarの内部バージョンと呼んでいます。初期のサンプルは単純な単一バイトXOR方式を使用していましたが、バージョン1.5ではChaCha20が採用されました。

バージョン1.8以降では、この暗号がさらに変更され、通常の識別・復号作業を困難にしています。

しかしバージョン2.0からは、独自のバイトコードインタープリタと、実装の詳細がビルドごとに変化する独自ストリーム暗号を組み合わせた多層的な方式へと切り替わりました。

この新しい仮想マシンは意図的に最小限に設計されています。バイトコード配列をフェッチ・デコード・実行のループで処理し、各バイトを256エントリのまばらなオペコードディスパッチテーブルへのインデックスとして利用します。

実際にハンドラーが割り当てられているのは14エントリのみで、未割り当てのエントリに当たると解釈は停止します。スタックや複数レジスタを備えた完全な仮想プロセッサを実装するのではありません。

Vidarは主に1バイトのアキュムレータ、直前の出力バイトの値、出力インデックス、そして変化するXORキーに依存しています。

各ハンドラーはXOR、加算、減算、ビット回転、ビット反転、乗算、置換テーブル参照といった小規模な演算を行います。

あるオペコードはデコード済みバイトを出力し、それを直前の出力値として保持したうえで、アキュムレータの状態へフィードバックします。

これによりインタープリタはコンパクトに保たれる一方、保護対象の各文字列は、読み取り可能な平文でも通常の暗号化データでもない、不透明なバイトコードとして見えるようになります。

このVMにハードコードされた4バイトのXORキーはビルドごとに異なり、アキュムレータのシード値としても機能します。

オペコードの割り当て、定数、置換テーブルもビルドごとに変化します。したがって、あるサンプルの復号のために作成されたスクリプトやシグネチャが、根底にある難読化解除の目的が同じであっても、次のサンプルにそのまま通用するとは限りません。

Zscaler ThreatLabzはこの進化の過程を追跡し、Vidarが単純なXOR保護から改変版ChaCha20を経て、最終的にはVM支援型の設計と可変の暗号ロジックを組み合わせた方式へと移行したことを明らかにしました。

独自バイトコード実行

Vidarはこの仮想マシンを2つのモードで利用します。文字列を直接デコードするモードと、第2段階の復号処理で使う素材を復元するモードです。

Image

後者のワークフローでは、VMの出力が独自ストリーム暗号のキーとナンスを提供し、それを使って別のciphertext配列を復号します。

バージョン2.0と2.1では、先頭9バイトがキー素材として使われますが、バージョン2.2以降ではこれが8バイトに変わります。いずれのバージョンでも、末尾4バイトはナンスとして使用されます。

ThreatLabzは2種類の暗号方式を確認しました。Vidarのバージョン2.0と2.1は、独自の128ビット状態、8バイトのキー、4バイトのナンス、そしてサンプルごとに異なるクォーターラウンドの回転処理を備えた、ChaCha由来の改変設計を使用しています。

バージョン2.2からは、マルウェアはARX(加算・回転・XOR)方式のストリーム暗号へと移行しました。

このARX実装では、復元したキーをFNV-1a素数を使って32ビットの状態に組み込んだのち、黄金比の小数部分に由来する定数0x9E3779B9を用いてナンスのバイトを処理します。

各ビルドは、ciphertextをXOR復号するための1バイトのキーストリームへと状態を畳み込む前に、それぞれ異なる一連の算術演算・ビット演算と定数を適用します。

この設計により、平文の文字列や安定した復号パターン、固定された定数に基づく静的なYARA形式のマッチングは困難になります。

また、サンドボックスや自動トリアージのシステムにも負荷をかけます。これらのシステムは、復号された値を観測できるところまでマルウェアを実際に実行するか、あるいはそのバイトコードエンジンを正確にエミュレートする必要に迫られるためです。

防御側は、文字列そのものよりも挙動やテレメトリを優先すべきです。不審なブラウザデータの収集、認証情報ストアへのアクセス、ウォレットの標的化、アーカイブの準備、異常な外向き通信、そしてプロセス実行チェーンは、依然としてより信頼できる検知の足がかりとなります。

研究者は、インタープリタにインストゥルメンテーションを施したり、実行時にデコード済みの出力をダンプしたり、あるいは小規模なオペコードセットをエミュレートしたりすることで、ビルドごとの文字列を復元することも可能です。

Splunkの研究者も同様に、Vidarの亜種が独自の仮想化と解析対策のチェック機能を利用していることを確認しています。これにはエンドポイントセキュリティ製品、サンドボックスの兆候、CPU数、ストレージ容量、RAMに関するチェックが含まれます。

Vidarの今回の難読化は、データ保護のために強力な暗号技術を導入したものではなく、むしろビルドごとの低コストな変化を実運用に落とし込んだものです。

そのトレードオフは効果的です。インターフェースを安定させることでマルウェアの保守性を保ちつつ、オペコードや定数、シード値、ARXの処理手順を絶えず変化させることで、静的シグネチャの価値を継続的に失わせているのです。

侵害指標(IOC)

IOC 説明
1628bb03db87f67661349e169d73ee14ed490bdbf22abfbda08ccc9ebe237974 Vidar v2.0
625a381981fc2d4c25c981d98b1d66bb2cf5da2dde2f590add0673a857d5b074 Vidar v2.5
2d43d592630ad1e012da63ef7279f95dd4a8e94964e12ca2f996051875574fa6 Vidar v3.1
979048a749d8f28d877c7068b1b336ecd1e349869dfb1d7c68118f90e4099bc4 Vidar v3.4

注: IPアドレスおよびドメインは、誤って名前解決やリンク化されるのを防ぐため、意図的に無効化表記(例: [.])にしています。再度有効な形式に戻す場合は、MISP、VirusTotal、あるいは自組織のSIEMなど、管理された脅威インテリジェンスプラットフォーム上でのみ行ってください。

SOCのアラート調査を1件あたり21分短縮。即座にIOCコンテキストを得て、迅速な対応を可能にするSOC強化ツール: TI Lookupを自社のSOCに統合する

翻訳元: https://gbhackers.com/custom-bytecode-execution/

本記事は gbhackers.com の記事を翻訳・要約したものです。