サンドボックス回避術の海を渡る

A pictorial depiction of a sandbox evasion

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

概要

マルウェアの作成者は、マルウェアがサンドボックス内で実行されていることを検出すると、悪意のある動作をしないようにあらゆる手を尽くします。そのような場合、検出が困難な独自のサンドボックスを作成することが、セキュリティ防御担当者にとって最善の対策になることがあります。世の中には多くのサンドボックス アプローチがあり、それぞれに長所と短所があります。本書では、カスタムメイドのアプローチを選択した理由について、さらにその際に対処する必要があった回避の種類とそれらへの対処方法について説明しします。

マルウェアの作成者がサンドボックスを検出する具体的な方法には多くのバリエーションがありますが、全体的なテーマは、環境の特性をチェックして、それが自動システムではなく、ターゲット ホストに見えるかどうかを確認することです。

パロアルトネットワークスのお客様は、高度なWildFireを通じ、本稿で解説する回避行為への検出力を高められます。

関連するUnit 42のトピック Sandbox, WildFire, evasive malware 

目次

回避の専門家になった経緯
計装または「フック」のチェック
計装の回避への対処
仮想環境の検出
VM回避への対処
人間の操作の欠如
人間の操作を利用する回避への対処
タイミングとコンピューティング リソースを利用する回避
タイミングを利用する回避への対処
ポケットの中身のチェック
ポケットの中身のチェックへの対処
結論
IoC

回避の専門家になった経緯

WildFireマルウェア チームは、マルウェア分析の世界で毎日を過ごすことで、サンドボックス回避の専門家になったと言うこともできるでしょう。チームのSlackチャンネルにはここ数年にわたって「これを見て!」というメッセージが書き込まれ、新しい回避手法を発見した喜びを分かち合ってきました。このような手法を解き明かすことは、検出率の向上に貢献するというチームのミッションの重要な部分を占めています。

マルウェアの作成者は、マルウェアが「本物の」ターゲット ホストで実行されているかどうかをチェックするために、ブラウザのキャッシュにあるCookieの数を数える、ビデオ メモリが少なすぎないかチェックするなど、膨大な数の手法を駆使します。サンドボックス回避は多数存在し、1つの記事で扱うには多すぎるので、最初によく遭遇するいくつかの主要なカテゴリについて説明し、次にそれらへの対策について説明します。

計装または「フック」のチェック

最初の大まかな回避カテゴリは、サンドボックス計装(instrumentation)の検出です。これは、間違いなく最も広く使用されている手法の1つです。最も一般的な例は、APIフックのチェックです。なぜなら、APIフックは、サンドボックスやアンチウイルス ベンダーが、分析中の実行可能スクリプトによるすべてのAPI呼び出しを計装してログに記録するために使用する共通の方法だからです。これは、一般的な関数のプロローグをチェックして、それらがフックされているかどうかを確認する程度の簡単なものです。

図1では、Windows 10のCreateFileAのプロローグの逆アセンブルを示し、それがサンドボックスで計装された場合にどのように見えるかを示しています。

図1は、Windows 10のCreateFileAのプロローグの逆アセンブルを示しています。3つのボックスがあります。左側のボックス1は、kernelbase.dllの通常のCreateFileAプロローグを表します。中央のボックス2は、同じCreateFileAのフックされたバージョンで、サンドボックス フック ハンドラを示すボックス3に向かう矢印とボックス3から戻る矢印が示されています。
図1. システムAPIの関数に対する一般的なサンドボックス フック。

ご覧のように、これを攻撃者が検出するのはとても簡単であり、この手法が世の中で最も一般的に見られる回避の1つであるのはそのためです。

この興味深いバリエーションとして、アクティビティがログに記録されずに密かに実行できるよう、マルウェアが既存のフックを検出して解除する手法があります。これは、マルウェアの作成者がターゲット ホスト上で検出されずにエンドポイント プロテクションをすり抜けたい場合に使用されます。

図2に、GuLoaderZwProtectVirtualMemory関数のプロローグのバイトのパッチを取り消して、元の機能を復元する例を示します。

図2は、GuLoaderがシステムAPI関数の計装のフックを解除する前と後のスクリーンショットです。ZwProtectVirtualMemory関数のプロローグのバイトのパッチが解除されています。
図2. GuLoaderによるシステムAPI関数の計装のフック解除。

計装の回避への対処

マルウェアの作成者が計装を検出するのを防ぐための基本は、分析中のプログラムから見える部分は通常の状態から何も変更しないということです。このアイデアを検出戦略の中心にするサンドボックスが増えています。OS内は1バイトも変更しないほうが、回避耐性が高くなります。

コードを変更してAPIを計装するのではなく、仮想化を使用して気付かれないように分析中のプログラムを計装するのが良い戦略です。図3に示すように、ゲストVMの外部からマルウェアを計装することには、多くの利点があります。

図3に、2つの図を並べて示します。左側の図には、ゲスト仮想マシンのプログラム分析コンポーネントと、それが実行するマルウェア サンプルを示します。右側の図には、同じ仮想マシンの外にあるホスト オペレーティング システムを示します。
図3. ゲスト内フッキング エンジンとハイパーバイザベースのフッキング エンジン。左: プログラム分析コンポーネントは実行するマルウェア サンプルとともにゲストVM内に存在。右: 分析コンポーネントはすべてゲストVMの外に存在し、したがって分析中のプログラムには見えていない。

仮想環境の検出

広く使用されているもう1つの回避カテゴリは、ファイルが仮想マシン(VM)で実行されていることの検出です。ここでは、少ないCPUコア数、システム メモリ、ビデオ メモリ、画面解像度のようなリソースのフィンガープリントなどが行われます。特定のVMのアーティファクトのフィンガープリントが行われる場合もあります。

ベンダーは、サンドボックスを構築する際、KVM、VirtualBox、Xenなど、多数のVMソリューションから選択できます。それぞれにさまざまなアーティファクトや特異性があり、それらは、その下にあるVM内で動作するソフトウェアで検出可能です。

これらの特異性の中には、VMwareのバックドア インターフェイスのチェック、OSに提示されたハードウェアとQEMUが提供する仮想ハードウェアが一致するかどうかのチェックなど、特定のシステムに固有のものもあります。他のアプローチでは、一般的に単にハイパーバイザを検出できます。たとえば、Mark Limは、多くのハイパーバイザがトラップ フラグの動作を誤ってエミュレートしているという事実を利用した、ハイパーバイザの一般的な回避を記事で取り上げています。

マルウェアがVMware仮想マシン内で動作しているかどうかを判断するための最も古く、最も広く使用されているメカニズムの1つでは、VMwareのバックドア インターフェイスを使用してVMwareハイパーバイザからの有効な応答があるかどうかを確認します。図4に、そのようなチェックの例を示します。

図4は、マルウェアがVMware仮想マシン内で実行されているかどうかをチェックして、有効な応答があるかどうかを確認するコード行のスクリーンショットです。
図4. マルウェアがVMware仮想マシン内で実行されているかどうかのチェック。

マルウェア ファミリは、Windows Management Instrumentation (WMI)のクエリを使用して、コンピュータ メーカーやモデルの情報をクエリすることもできます。これにより、システムに関する情報を取得し、既知のサンドボックスやハイパーバイザの文字列と比較できます。

図5に、これを使用して、VMware、Xen、VirtualBox、QEMUに対してクエリを実行する方法を示します。多数のサンドボックス対抗手法を備えたオープンソース ツールであるAl-Khaserでも、これと同じ手法を確認できます。

図5は、Windows Management Instrumentationのクエリを使用してシステム情報を収集するコード行のスクリーンショットです。
図5. WMIクエリを使用したコンピュータ情報の収集。

図6に、マルウェアが仮想環境で実行されているかどうかを明らかにするためにやり取りする可能性があるソフトウェア コンポーネントを示します。

図6は、malware.exeが、ゲスト仮想マシン内およびホスト オペレーティング システム内でさらに他のコンポーネントにアクセスする様子を示しています。これらには、準仮想化デバイス ドライバー、仮想マシン バックドア インターフェイス、仮想ハードウェア スタック、および仮想マシン モニターが含まれます。
図6. プロセスがVM内に存在するかどうかを評価するためにやり取りする可能性があるその他のコンポーネント。

また、ゲストOSが実行されているVMプラットフォームに関する手がかりを容易に得ることができるような大量の情報が、ゲストVMの周囲に散在していることもよくあります。どのケースでも、詳細については、使用するVMインフラストラクチャ(VMware、KVM、QEMUなど)に依存します。

以下にマルウェアの作成者がチェックできる内容の例をいくつか示します。

  • VM固有のハードウェア、ドライバー、またはサービスを示すレジストリ キー パス。
  • VM固有のドライバーまたは他のサービスのファイルシステム パス。
  • 一部のVMインフラストラクチャに固有のMACアドレス。
  • 仮想ハードウェア(たとえば、クエリによりネットワーク カードがIntel e1000であることがわかった場合、このカードは何年も製造されていないため、高い確率でQemuハードウェア モデルで動作していることが推測できます)。
  • 準仮想化をサポートするVMプラットフォーム固有のサービスまたはVMwareツールのようにユーザーの利便性を高めるシステムを示す実行中のプロセス。
  • 多くのケースでVMプラットフォームのゲストをソフトウェアに通知するのに役立つCPUID命令。

VM回避への対処

これらの対処での主な問題は、主流の仮想化プラットフォームの選択肢は、マルウェアの作成者に広く知られているという点です。ほとんどのサンドボックスは実装しやすくするためにKVM、Xen、QEMUなどのシステムをベースにしているので、この種の回避は特に対策するのが困難です。

世の中の主流のVMプラットフォームはすべて、サンドボックス回避の対象になっています。問題は、マルウェア分析をサポートする独自のカスタム ハイパーバイザを作成することこそがこの種の回避に効果的な対策であることです。

そこで、実行しました。

検出チームは数年前に、マルウェア分析に特化した独自のカスタム ハイパーバイザを実装することを決定しました。開発チームは、動的分析を目的とする独自の仮想化プラットフォームを構築する(しかもゼロから!)ために、どんな苦労も惜しみませんでした。

この決定には、2つの利点があります。1番目は、他のVMインフラストラクチャに対して使用されるのと同じフィンガープリント手法の影響を受けにくいことです。バックドア インターフェイスは存在しませんが、他とは異なる仮想ハードウェアおよびまったく異なるコードベースがあります。

2番目の利点は、独自のシステムを構築しているので、マルウェアが回避目的で策略を使用しても、それがどこであろうと容易にその問題に適応して対処できることです。たとえば、前述のリンク先の記事では、多くのハイパーバイザがゲストVMのトラップ フラグを誤ってエミュレートしていることについて説明しています。弊社のマルウェア アナリストは開発チームとしっかり連携して、影響を受けず、正しくエミュレートすることができました。

人間の操作の欠如

このカテゴリには、特定の人間の操作を必要とする回避が含まれます。たとえば、マルウェアの作成者は、「本物の」ユーザーが操作するシステムなら発生するであろうマウス クリックなどのイベントを期待しますが、一般的な自動分析プラットフォームではそのようなイベントは発生しません。マルウェア ファミリは、多くの場合、人間の操作をチェックし、ユーザー アクティビティがシミュレートされているため、システムを操作するユーザーがいないように見える場合は実行を停止します。

人間の操作のチェックに関して確認されている全体的なテーマを以下に示します。

  • ユーザーに操作を要求します。たとえば、確実にデトネーションさせるためには、サンドボックスが認識しない可能性のあるダイアログ ボックスまたは偽のEULAをクリックする必要があります。
  • マウス クリック、マウスの移動、およびキーの押下をチェックします。マウス イベントの位置やキーストロークのタイミングまで分析して、「自然」なものなのか、プログラムにより生成されたものなのかを判断します。
  • ドキュメントにマクロを組み込んで、スクロール、スプレッドシートのセルのクリック、別のワークシートのタブのチェックなどの人間の操作の証拠をチェックします。

図7に具体例を示します。この例で、マルウェアは、最後のユーザー入力からの経過時間(GetLastUserInput)とシステム起動からの経過時間(GetTickCount)を取得します。最後にキーが押されてからの経過時間を比較して、システムで何らかのアクティビティがあったかどうかを検出できます。

図7は、マルウェアがシステム起動からの経過時間と最後のユーザー入力からの経過時間の両方を取得する方法を示す逆アセンブラのスクリーンショットです。
図7 デトネーションに必要なユーザーの操作。

人間の操作を利用する回避への対処

サンドボックスを実装している場合、仮想のキーボード、マウス、およびモニターを制御できます。何らかの理由により、分析中の実行可能スクリプトでキー入力が必要な場合、分析処理にキー押下を送信したり、正しいボタンをクリックして実行可能スクリプトの実行を続行することができます。これは実際のところ、実行中のマルウェアに対して説得力のあるショーを見せるために、人間なら実行するであろう動作を自動的に実行する方法を知っているかどうかの問題に過ぎません。

VM検出の問題における他のすべての領域と同様に、マルウェア ファミリが何を探しているのかに常に注意を払い、回避に対する戦略を継続的に改善する必要があります。最近の例では、Excelスプレッドシートの複数のセルを1つずつマウスでクリックする必要があるマルウェアがありました。これが将来私たちに対して使用される場合に備えて、信頼できる検出方法を構築するために、さらに努力する必要がありました。

タイミングとコンピューティング リソースを利用する回避

初期のころ、サンドボックスを回避するために最も広く使用された方法として、悪意のある動作を実行する前に、約1時間のsleepを呼び出すというものがありました。すべてのサンプルを数分以上実行することは実現不可能なので、この呼び出しにより、ほとんどのサンドボックスが使用する短い分析時間に比べてはるかに長くマルウェアが存在することが保証されます。

これに対して、サンドボックスの作成者は長いスリープを短くするsleepを計装しました。このいたちごっこを何回も繰り返した後、現在では、マルウェアがサンドボックス内で時間を浪費して意味のある分析結果を得るのを妨害する方法は、驚くほど多様に絶え間なく進化しています。

図8に、WindowsタイマーとWindowsメッセージを使用する回避手法を示します。このアイデアは、毎秒起動するタイマーを実装し、タイマーのコールバックを実行する際に内部変数をインクリメントするというものです。

この変数が特定のしきい値に達すると、別のWindowsメッセージを送信して、マルウェアの実行を開始するようにサンプルに通知します。この回避における問題は、サンドボックスでタイマーのタイムアウトを単純に短縮すると、他のソフトウェアの実行を中断する可能性があるため、これを実行することはできないという点ですが、それでもどうにかして実行する必要があります。

図8は、Windowsのタイマーとメッセージを使用してタイマーを実装する回避手法を示すコード行のスクリーンショットです。
図8. タイマーとWindowsメッセージを使用するsleepの例。

図9に別の例を示します。ここでは、悪意のある実行可能スクリプトは、単にループ内でタイム スタンプ カウンタ命令を呼び出しています。

図9は、sleepループを示すコード行のスクリーンショットです。マルウェア実行可能スクリプトは、ループ内でタイム スタンプ カウンタ命令を呼び出します。
図9 タイム スタンプ カウンタ命令を使用するsleepループ。

タイミングを利用する回避への対処

タイミングを利用する回避は、状況によっては対策が非常に難しい場合があります。前述したように、sleepの引数やタイマーはいつでも調整できますが、これで問題が完全に解決するわけではありません。

もう1つの戦略として、ハイパーバイザが制御下にあることを利用して、すべてのハードウェアとソフトウェアを制御してゲストVM内の時間を速く進める手法を使用するというのも有効であることがわかりました。これは、引数を変更したりフックをインストールしたりしなくても実行できます。1時間の実行可能スクリプトを、実際には数分以内に完了できます。これにより、悪意のあるコードに到達するまでの時間を短縮できます。

ジャンク命令ループやVM exitループは、おそらく最も対策が難しいシナリオです。マルウェアの作成者が数百万のCPUID命令を実行した場合、これはハイパーバイザの下で実行すると指数関数的に長い時間がかかるので、コードがVMで実行されていることを示す決定的証拠になります。マルウェア分析用に調整したカスタム ハイパーバイザは、この種のアクティビティも検出してログに記録できるので、このような状況でも有効です。

ポケットの中身のチェック

「ポケットの中身(Pocket Litter)」はスパイ活動の分野に由来する用語であり、ポケットの中にあるものを「容疑者自身の証言の確証または反論」に利用できるというものです。これは、マルウェアの作成者によってその環境が本物のターゲット ホストである証拠を示しているかどうかがチェックされるすべての回避に対して、弊社内で採用している用語です。

サンドボックス環境では、通常、「ポケットの中身」のチェックには、システム稼働時間が適度な長さであること、マイ ドキュメント フォルダに十分な数のファイルがあること、システムのブラウザ キャッシュに十分な数のページがあることなどを確認することが含まれます。これらはすべて、システムがサンドボックス環境ではなく「本物」であることを裏付けるのに役立ちます。他のカテゴリと同様、無数のバリエーションがあるように思われます。

図10は、マルウェアが、プロセッサが2つ以上使用可能かどうか、十分なメモリが使用可能かどうかをチェックする例です。一般に、サンドボックス環境では通常のPCほど多くのメモリが使用可能ではないので、このチェックにより、ターゲット システムがデスクトップPCなのか、サンドボックス環境内で実行されているのかをテストしています。

図10は、マルウェアが、プロセッサが2つ以上使用可能かどうか、およびメモリの可用性をチェックするコード行のスクリーンショットです。これにより、マルウェアは、ターゲット システムがデスクトップPCなのか、サンドボックス内で実行されているのかを確認できます。
図10 最小限必要なプロセッサ数と実行に必要なメモリのチェック。

図11は、ボリューム ディスクのシリアル番号が既知のアンチウイルス ベンダーで使用されるエミュレータのものと一致する場合に、AutoIt実行可能スクリプトが終了する例です。

図11は、ボリューム ディスクのシリアル番号が既知のアンチウイルス ベンダーで使用されるエミュレータのものと一致する場合に、AutoIt実行可能スクリプトが終了するコード行のスクリーンショットです。チェックされているボリュームのシリアル番号が表示されます。
図11 ボリュームのシリアル番号のチェック。

ポケットの中身のチェックへの対処

対処という観点では、大まかにこれ1つで使用可能なすべての手法に対応できるというようなものはありません。むしろ、できる限りケース バイ ケースで対処するようにしています。

たとえば、特定の場所にある特定の種類のファイルのチェックが回避に使用されていることが判明した場合、関連するすべてのサンプルが確認できるようにそのファイルを追加します(この追加がVMイメージに対して無害な変更であると思われる場合)。このポケットの中身というアプローチは、すべての攻撃者の標的に対処する万能薬は実際には存在しないので、いたちごっこのように感じられるかもしれません。粘り強く対処することが重要です。

結論

すべてのサンドボックス回避を「解決した」と主張しているのではないことを強調しておきます。実際、回避の種類がほぼ無限に存在することを考えると、状況はまったく逆です。

ここまで述べた内容から導き出される結論があるとすれば、それは、世の中のサンドボックス回避の数が多すぎて、それぞれに効果的に対処することはできないということです。自分のサンドボックスは100%回避できないと主張する人は、現実を直視する時期が来ています。

本書では、大まかなカテゴリの回避について概要を説明し、それらに対処するために弊社で使用している戦略について説明しました。すべての回避に包括的に対処することはできないので、多層防御戦略を推奨します。これにより、回避が成功してペイロードが実行されない場合でもマルウェアを検出できるように、検出システムを構築できます。

WildFireチームにとって、これは検出の唯一の基盤として単にシステムAPI呼び出しと他の監視可能なアクティビティに依存することから脱却することを意味します。弊社には独自のハイパーバイザがあるので、すべてのハードウェアとソフトウェアを制御できることを利用して、実行中のマルウェアから見えないようにVM内にソフトウェアを計装することができました。

Advanced WildFireのハイパーバイザのメモリ解析に関する前回の記事で述べたように、弊社の目標は、メモリ内のマルウェアを対象とする新しい種類の分析エンジンを作成することです。本書で説明したどの回避手法の場合も、それを実行して分析されていることを正しく検出するには、ある時点でそのためのコードがメモリ上に存在する必要があります。

図12は、メモリ内のマルウェアを検出するプロセスを示しています。マルウェアは、メモリに読み込まれた後、ペイロードをダウンロードします。ペイロードは、サンドボックス内で実行されていることを検出すると、動作を終了します。Advanced WildFireは、この最後のステップでサンドボックスの実行中にメモリ内のペイロードを対象にします。
図12. メモリ内のマルウェアの検出。

弊社のシステムでは、検出の焦点を、実行中のメモリ内の差分に移しています。図12に示すように、ペイロードまたは任意のコードがメモリ内でデコード、解凍、または復号化された場合、このシステムでは、それを視認し、確実に捕捉することができます。

最後に、自動化されたマルウェア分析システムを構築する場合のアドバイスとして、世の中の幅広いカテゴリのサンドボックス回避に対応するという観点で、できる限り柔軟性を高めることを推奨します。本書で説明したテーマのさまざまなバリエーションに今後遭遇することは間違いありません。

また、サンドボックス回避に対して耐性を持つシステムを構築することを推奨します。言い換えると、他がすべて失敗し、悪意のある動作を精査する実行イベントがない場合でも、フォールバックできる別の方法を用意する必要があります。ペイロードが休止したまま実行されないことになった場合でもAdvanced WildFireでメモリを分析して回避型マルウェアを検出できるというのは、その実際の例です。

マルウェアの作成者が検出を回避するために編み出したあらゆる手口を紹介したこの長い記事をお読みいただき、ありがとうございました。 楽しい脅威ハントを!

パロアルトネットワークス製品をご利用中のお客様は本稿で取り上げた脅威から高度なWildFireによって保護されています。

IoC

SHA256 説明 マルウェアファミリ
3bf0f489250eaaa99100af4fd9cce3a23acf2b633c25f4571fb8078d4cb7c64d WMIクエリ Trickbot
e9f6edb73eb7cf8dcc40458f59d13ca2e236efc043d4bc913e113bd3a6af19a2 SetTimerを使うタイミング攻撃 Sundownのペイロード
3450abaf86f0a535caeffb25f2a05576d60f871e9226b1bd425c425528c65670 タイム スタンプ カウンタ命令を使用するsleep VBCrypt
091ffdfef9722804f33a2b1d0fe765d2c2b0c52ada6d8834fdf72d8cb67acc4b ボリューム ディスクのシリアル番号のチェック Zebrocy
SHA256 説明 PUA (迷惑アプリ)
96a88531d207bd33b579c8631000421b2063536764ebaf069d0e2ca3b97d4f84 VMwareチェック PUA/KingSoft
de85a021c6a01a8601dbc8d78b81993072b7b9835f2109fe1cc1bad971bd1d89 GetLastUserInputチェック PUA/InstallCore