Log4j Resource Center

1ビットでサンドボックスを回避するトラップフラグ(TF)とLampionマルウェアでの悪用例

Evad Sandboxes with a single bit

This post is also available in: English (英語)

概要

Unit 42は、インテルのCPUレジスタにある特定の1ビット(Trap Flag)をマルウェアが悪用した場合、汎用的にサンドボックスの検出が回避可能になることを発見しました。マルウェアはこの1ビットを設定した後でCPUの応答を監視することにより、自身が物理マシンで実行されているのか仮想マシン(VM)で実行されているかを検知できます。

「サンドボックス」とは、ある検体に悪意があるかどうかを検出するさいによく利用される技術です。サンドボックスでは、実行されたバイナリの動作をコントロールされた環境内で分析します。サンドボックスには、限られた計算機資源で大量のバイナリを解析するという課題があることから、その構築には仮想マシン(VM)が使われます。これに対し、検出を逃れたいマルウェアは自身が物理マシンと仮想マシンのどちらで実行されているのかを判別しようとします。そして、自身が仮想マシン環境で実行されていることを知ると、実行を終了したり偽の出力を提供して真の意図を隠そうとします。

最も一般的な回避技術は、マルウェアが実行環境に対してさまざまなシステムチェックを行うものです。たとえば画面の解像度やハードディスクサイズ、物理メモリサイズが普通とちがっていないかを調べます。サンドボックス側もこれに対抗し、これらのチェックが行われたときに偽の情報をマルウェアに返すように設定することができます。

本稿は、マルウェアが仮想マシンや物理マシンにおけるCPUの動作の違いをCPUレジスタの1ビットを使うだけで検知しているその方法を記述します。

パロアルトネットワークスのお客様は、Cortex XDR またはWildFire脅威防御セキュリティサブスクリプションを有効にした次世代ファイアウォールにより同様のサンドボックス回避技術を使用するマルウェアファミリから保護されています。

1ビットによるシングルステップモード: Trap Flag(TF)

「トラップフラグ」有効後のCPUの動作を確認することで、マルウェアはサンドボックス内でのVM使用を検知できます。

「トラップフラグ(以下TF)」は、Intel x86 CPUアーキテクチャのEFLAGSレジスタの8番目のシングルビットのことです。ある1つの命令の実行前にTFを有効にしておくと、CPUは命令完了後に例外を発生させます(シングルステップモード)。この例外でCPU実行を停止させれば、レジスタやメモリロケーションの内容を例外ハンドラで調べることができます。なおCPUは、コード実行を継続するならその前にTFをクリアしておく必要があります。

VMが使用されているかどうかを判断するために、マルウェアは、TFが有効な状態でVMを終了させる特定の命令(CPUID、RDTSC、INなど)を実行後、シングルステップ例外が正しいCPU命令に渡ったかどうかを確認することができます。VMの終了時は、ハイパーバイザ(VMM(Virtual Machine Monitor)とも呼ばれる)が物理CPUに起こる影響をエミュレートします。

以下の一連の命令は、物理マシンでTFを有効化後に起こるCPUの動作を説明したものです。

TF有効化後のCPUの動作。一連の命令が表示されている
図1 TFを有効にするCPU命令

最初の3つの命令がCPUのEFLAGSレジスタのTFビットを有効にしています。そしてTFが有効な状態でRDTSCが実行されています。物理マシンの場合、例外は最初のノーオペレーション(NOP)命令(0x00401073)に渡ります。ここでは、TFを有効にする命令を実行した直後の命令で例外が発生していることに注意してください。

この例外はTFを有効にする命令実行後の最初のNOP命令(0x00401073)に渡ります。
図2 物理マシンでの実行

ところが同じ一連の命令をVMで実行するとその効果が異なります。VMではRDTSCを実行するとVMが終了してしまいます。ハイパーバイザはRDTSC命令の動作をエミュレートするという通常のタスクを実行します。ところがTFのエミュレーションが正しくないハイパーバイザ実装では、TFが無視されてコード実行が最初のNOP命令まで続くことになります。最初のNOP命令の実行中にTFがハイパーバイザにより処理されなかったため、TFはまだ有効な状態です。この結果、2つめのNOP命令(0x00401073)で例外が発生します。これを正しく実装をするには、ハイパーバイザがまずVM終了の原因となった命令をエミュレートしてTFをクリアし、その後でデバッグ例外を注入する必要があります。

2回目のNOP命令(0x00401073)で例外が発生した。これによりVMの終了とTFのクリアが行われた
図3 仮想マシンでの例外

サンドボックス回避の手法として、マルウェアは上記の命令列に加えて例外ハンドラを使用し、どの命令で例外が発生したかを調べます。次のセクションで、この技術を実際に利用してサンドボックスを回避していたマルウェアファミリの例を紹介します。

実例

Lampionはポルトガルのユーザーをターゲットにしていたマルウェアです。Lampionはサンドボックスによる検出回避のため、複数のシステムチェックを採用していました。その1つが、前章で述べたTFによるシングルステップモードの活用です。

Lampionはすべてのシステムチェックをx86のアセンブリ命令と最小限のWindows APIコールで実装していました。これにより、Lampionのサンプルはサンドボックスからその動作を隠すことができました。Lampionのサンプルは、自身がVM中で実行されていると判断すると終了します。またシステムチェックには複数のリバースエンジニアリング対策技術が組み込まれており、アナリストの目を逃れようとしています。

以下のスクリーンショットはLampionのサンプルに隠された命令のスニペットで、それらの命令がシステムチェックを行っています。

Lampionのサンプルは、隠された命令でシステムチェックを行う
図4 サンドボックス回避に使われたLampionの命令

以下は、VMを終了させる命令に対してTFを有効にすることで、Lampionがサンドボックスのシステムチェックの1つを実行する様子を示した疑似コードです。

LampionがサンドボックスのTFを有効にしてVMを終了させ、システムチェックを行う疑似コード。
図5 TFを使ってサンドボックス対策を行うLampionの疑似コード

RDTSC命令の直後の命令はNOPです。NOP命令のバイトコードは0x90です。例外ハンドラは、ContextRecord構造体を走査し、例外発生時のEIP(Extended Instruction Pointer Register)内の命令のアドレスを特定します。その命令が「0x90」バイトと比較され、チェックが失敗すればマルウェアは終了します。

次のスクリーンショットは、例外発生時、EIP=0x7F0E4Eであることを示しています。

例外発生時、EIP=0x7F0E4Eであることを示したスクリーンショット
図6 例外が発生した命令のアドレス

マルウェア作者とサンドボックス作者の戦い

長年にわたり、効果的な分析を防ぐために回避テクニックを駆使するマルウェア作者と、その回避テクニックを破る新機軸を研究するサンドボックス作者との間ではいたちごっこが続いています。

これがパロアルトネットワークスがマルウェア解析用に独自カスタムハイパーバイザを構築した主な理由の1つです。カスタムハイパーバイザであれば、仮想化レイヤを含むソフトウェアスタックを完全にコントロールできるので、新たな脅威にも迅速に対応できます。この特定事例では、トラップフラグの不適切なエミュレーションに関する問題が特定された後すぐに弊社ハイパーバイザチームがテストを実施し、修正プログラムを導入できました。このため、この検出回避問題は同技術を使うすべてのマルウェアサンプルについて解決されています。

パロアルトネットワークスのお客様は、Cortex XDRまたはWildFireと脅威防御セキュリティサブスクリプションを有効にした次世代ファイアウォールにより同様のサンドボックス回避技術を使用するマルウェアファミリから保護されています。インテルのCPU命令やレジスタを悪用した他の類似のサンドボックス回避技術は、WildFireに対しては機能しません。AutoFocus をご利用のお客様は、本稿で取り上げたマルウェアをLampionタグで追跡できます。

IoC

Lampion サンプル

  • EB3F2BE571BB6B93EE2E0B6180C419E9FEBFDB65759244EA04488BE7C6F5C4E2