VBS エンクレーブの悪用による回避型マルウェアの作成

Ori David

執筆者

Ori David

February 25, 2025

Ori David

執筆者

Ori David

Ori David は、Akamai の Security Researcher です。彼は、オフェンシブセキュリティ、マルウェア分析、脅威ハンティングに焦点を当てた調査を行っています。 

エンクレーブ内で動作するマルウェアは、メモリーベースの検出やフォレンジックでは発見されない可能性があります。
エンクレーブ内で動作するマルウェアは、メモリーベースの検出やフォレンジックでは発見されない可能性があります。

目次

概要

仮想化ベースのセキュリティ(VBS)は、最近の最も魅力的なセキュリティの進歩の 1 つです。OS の重要なコンポーネントを隔離する機能により、Microsoft は Credential Guard や Hypervisor-Protected Code Integrity(HVCI)などの機能を使用して、大幅なセキュリティ向上を実現しました。

VBS によって有効化される、しばしば見落とされがちな機能の 1 つが VBS エンクレーブ です。これは、プロセスの一部の領域を隔離し、他のプロセス、プロセス自体、さらにはカーネルからもアクセスできないようにする技術です。 

VBS エンクレーブにはさまざまなセキュリティアプリケーションが含まれており、Microsoft はこれらを使用していくつかの重要なサービスを実装しています。これには、物議を醸している リコール機能も含まれています。さらに、Microsoft は VBS エンクレーブのサードパーティ開発をサポートし、積極的に導入を推進しています。

エンクレーブはシステムのセキュリティを確保するのに役立ちますが、攻撃者にとっても非常に魅力的です。 エンクレーブ内で動作するマルウェアは、メモリーベースの検出やフォレンジックでは発見されない可能性があります

私たちは VBS エンクレーブを調査し、それが悪意のある目的でどのように使用される可能性があるかを理解することを目指しました。このブログ記事では、その主な調査結果について詳しく説明します。また、これまでに文書化されていない VBS エンクレーブの動作を調査し、攻撃者がその内部で悪性コードを実行するために利用するシナリオを説明し、「エンクレーブマルウェア」が使用できるさまざまな手法を検証することで、VBS エンクレーブについて詳しく説明していきます。

さらに、 Mirage(私たちが「脆弱なエンクレーブの持ち込み」と名付けた新しいアプローチ)に基づくメモリー回避技術も紹介します。攻撃者は正当なエンクレーブの古い、脆弱性のあるバージョンを使用して、このようなステルスな回避技術をどのように実装するのか、詳しく説明します。

仮想信頼レベル 

Windows は従来、プロセッサー・リング・レベルによって、ユーザーアプリケーションによる OS の改ざんを防いでいました。このハードウェアの機能では、OS とユーザーアプリケーションを分離できます。カーネルは ring0 で動作し、ring3 ユーザー・モード・アプリケーションから分離されます。このアプローチの問題は、攻撃者に OS を侵害するための比較的簡単なパスを提供してしまうことです。これが Kernel Exploit です。

Windows カーネルは非常に広範な攻撃面を公開しています。カーネル自体が公開するさまざまなサービスと同様に、膨大な数のサードパーティ製ドライバーによって、Kernel Exploit と思われるものが絶えず発生しています。 このような脆弱性を悪用するプログラムを使用することで、攻撃者は OS のあらゆる側面を制御できる可能性があります。ユーザー/カーネルモード の境界 は不十分であることが証明されました。

このギャップを埋めるために、Microsoft は仮想信頼レベル(VTL)の形で OS にセキュリティの境界を追加しました。VTL 権限はメモリーアクセスに基づいています。各信頼レベルにより、その下で実行されているエンティティにはそれぞれ異なる物理メモリーへのアクセス権限が与えられます。これらの権限により、下位の VTL は上位の VTL のメモリーにはアクセスできなくなります。

従来のプロセッサー・リング・アーキテクチャと同様に、VTL は OS を VTL0 から(最大で)VTL16 までのさまざまな実行「モード」に分離します。ring0 の権限が最も高いプロセッサーリングとは異なり、上位の VTL ほど権限は高くなります。

Windows は現在、VTL0 と VTL1 の 2 つ(VTL2 も使用されますが、このブログ記事では扱いません)の主要な信頼レベルを使用しています。VTL0 は、カーネルやユーザーモードのアプリケーションなど、従来の OS コンポーネントを実行するために使用されます。VTL1 は VTL0 よりも権限が高く、 セキュア カーネル モード隔離されたユーザーモードの 2 つの新しい実行モードを提供します。

セキュア カーネル モード

セキュア カーネル モードとは、ring0 VTL1 実行モードを指します。このモードは、セキュアカーネルを実行するために使用されます。カーネルが VTL1 で動作するため、通常のカーネルより権限が高くなっています。これらの権限を使用して、セキュアカーネルは通常のカーネルにポリシーを適用し、機密性の高いメモリー領域へのアクセスを制限することができます。

前述したように、カーネルは大きな攻撃面を公開しており、侵害されやすくなっています。カーネルからいくつかの権限を削除し、その権限をセキュアカーネルに付与することで、カーネル侵害の影響を軽減することができます。

理論的には、セキュアカーネルの侵害によって攻撃者がシステムを完全に侵害する可能性もありますが、このシナリオははるかに可能性が低くなります。なぜなら、セキュアカーネルは非常に限定的であり、サードパーティ製のドライバーをサポートしていないため、攻撃面が大幅に減少しているからです。

隔離されたユーザーモード

VTL1 では、「隔離されたユーザーモード」(IUM)と呼ばれる、別の興味深い実行モードも作成されます。これは、ring3 VTL1 実行モードを指します。IUM は、セキュアプロセスを実行するために使用されます。これは、VTL1 のメモリー隔離機能を使用する特別なタイプのユーザー・モード・プロセスです。IUM 内部のメモリーは、通常のカーネルを含む VTL0 コードからはアクセスできません。この実行モードは、Credential Guard などの隔離ベースの機能の 基盤となっています

つまり、VTL0/1 を導入すると、実行モードが 4 つになります(図 1)。

  • Ring0 VTL0:通常のカーネルモード
  • Ring0 VTL1:セキュア カーネル モード
  • Ring3 VTL0:通常のユーザーモード
  • Ring3 VTL1:隔離されたユーザーモード
つまり、VTL0/1 を導入すると、実行モードが 4 つになります(図 1)。 図 1:VTL の追加によって作成される実行モード

VBS エンクレーブとは

IUM によって有効になるもう 1 つの機能は、VBS エンクレーブです。VBS エンクレーブは、IUM 内に存在するユーザー・モード・プロセスの一部であり、ここには「エンクレーブモジュール」と呼ばれる DLL をロードできます。

モジュールはエンクレーブにロードされると、「信頼された実行環境」になります。エンクレーブ内のデータやコードは、VTL0 で実行されているものにアクセスできないため、改ざんや窃取を防ぐことができます(図 2)。この機能は、システムを侵害する可能性のある攻撃者から機密性の高い操作を隔離するのに役立ちます。

モジュールはエンクレーブにロードされると、「信頼された実行環境」になります。エンクレーブ内のデータやコードは、VTL0 で実行されているものにアクセスできないため、改ざんや窃取を防ぐことができます(図 2)。 図 2:VBS エンクレーブのメモリーレイアウト(出典:https://learn.microsoft.com/en-us/windows/win32/trusted-execution/vbs-enclaves)

ユーザー・モード・プロセスは、 専用の Windows API を呼び出してエンクレーブを作成し、そのエンクレーブにモジュールをロードして初期化することができます。エンクレーブモジュールは、この目的のために特別にコンパイルされた DLL の形式で提供されます。エンクレーブが初期化されると、ホスティングしているユーザー・モード・プロセスはそのメモリーにアクセスできなくなり、エンクレーブモジュールによってエクスポートされた関数を CallEnclave API を使用して呼び出すことによってのみ、エンクレーブと対話できるようになります。

図 3 は、このプロセスを実装するコードの例です( Microsoftがより詳細な例を提供しています)。

図 3 は、このプロセスを実装するコードの例です(より詳細な例は Microsoft が提供しています)。 図 3:VBS エンクレーブ作成コードの例

Microsoft は VTL1 へのアクセスを可能な限り制限することを目指しているため、DLL をエンクレーブにロードするためには、Microsoft が発行した特別な証明書を使用して適切に署名されている必要があります。このような署名なしでモジュールをロードしようとすると、失敗します。エンクレーブモジュールに署名するオプションは、信頼できるサードパーティにのみ委任されます。興味深いことに、 これらのモジュールを ロードできるユーザーには制限がありません。 署名されている限り、どんなプロセスでも、任意のモジュールをエンクレーブにロードできます

エンクレーブモジュールは小さな「計算ユニット」として機能することを目的としており、システムとのやり取りやシステムへの影響は非常に限られています。このため、エンクレーブモジュールは 最小限の API セットしか使用できず、ほとんどの OS コンポーネントにアクセスできません。

エンクレーブ内で使用可能な API は、VTL1 にロードされた専用ライブラリからインポートされます。たとえば、通常のプロセスは OS にサービスを要求する際に ntdll.dll ライブラリを使用しますが、エンクレーブモジュールは vertdll.dll を使用します。これは、syscalls を介してセキュアカーネルと通信するために使用される「代替」 ntdll です。

エンクレーブマルウェア

エンクレーブマルウェアの概念は、攻撃者にとって極めて魅力的です。それには次の 2 つの大きな利点があります。

  1. 隔離されたメモリー領域で実行される:エンクレーブのアドレス空間は、VTL0 で実行されているもの(EDR や分析ツールなど)にはアクセスできないため、検知が非常に複雑になります。

  2. 追跡不可能な API コール:エンクレーブ内からの API コールは EDR には検知されません。EDR は、システムライブラリ内にフックを配置してユーザーモードで API を監視し、ドライバーを使用してカーネル内のアクティビティを監視します。エンクレーブからトリガーされた API コールは、VTL1 から実行され、これらの「フック」された VTL0 コンポーネントを経由しないため、これらの手法では検出できません。

図 4 に、この利点を示します。Windows API を呼び出す通常のプロセスは、 NTDLL 内部のフックまたはカーネル自体を使用して監視できます。しかし、エンクレーブモジュールは VTL1 常駐 vertdll を通過して、セキュアカーネルへの呼び出しを実行します。両方とも EDR にはアクセスできません

図 4 に、この利点を示します。Windows API を呼び出す通常のプロセスは、NTDLL 内のフックまたはカーネル自体を介して監視できます。 図 4:通常のユーザーモードと IUM API コールのプロセスの違い

この可能性を認識し、私たちはエンクレーブマルウェアの概念を調査することにしました。この目的のためにエンクレーブを活用するためには、次の 2 つの疑問に答える必要があります。

  1. 攻撃者はエンクレーブ内でどのようにして悪性コードを実行するのか
  2. エンクレーブ内で実行に成功した攻撃者はどのような手法を使用するのか

攻撃者はエンクレーブ内でどのようにして悪性コードを実行するのか

前述したように、エンクレーブモジュールは、Microsoft が発行した証明書を使用して署名されている必要があります。つまり、エンクレーブ内で独自のコードを実行できるのは、エンクレーブモジュールによって承認されたエンティティだけです。それにもかかわらず、攻撃者にはいくつかの選択肢があります。

まず、攻撃者は OS の脆弱性を利用することができます。この一例は、Alex Ionescu 氏(Winsider Seminars&Solutions 在籍)が発見した CVE-2024-49706でした。これにより、攻撃者は署名されていないモジュールをエンクレーブにロードできます。この脆弱性は Microsoft によって修正されましたが、将来的に、意欲的な攻撃者が同様のバグを発見する可能性があります。

もう 1 つの簡単なアプローチは、正当な署名を取得することです。これは、Microsoft が Trusted Signing プラットフォームを介してサードパーティにエンクレーブ署名を公開しているため可能になります。決して簡単ではありませんが、高度な攻撃者が Trusted Signing エンティティへのアクセス権を取得し、独自のエンクレーブに署名できることもあります。

私たちは、これら 2 つのオプションに加えて、攻撃者が VBS エンクレーブ内でコードを実行できるようにする、デバッグ可能なエンクレーブモジュールの悪用と脆弱なエンクレーブの悪用の 2 つの追加テクニックについても詳しく調査しました。

デバッグ可能なエンクレーブモジュールの悪用

VBS エンクレーブモジュールを作成する際、開発者はそれを デバッグ可能になるように構成できます。この設定でモジュールをコンパイルすると、デバッグが可能になります。エンクレーブモジュールは VTL1 で実行されるため、デバッグは通常不可能です。デバッガーがエンクレーブメモリーにアクセスしてデータを取得したり、ブレークポイントを配置したりできないためです。図 5 に、エンクレーブ内のメモリーアドレスからのデバッガーの読み取りが失敗する例を示します。

図 5 に、エンクレーブ内のメモリーアドレスからのデバッガーの読み取りが失敗する例を示します。 図 5:デバッグ不可の VBS エンクレーブモジュールのメモリー読み取り試行

興味深いことに、デバッグ可能なエンクレーブモジュールが実行された場合、このモジュールは VTL1 にロードされます。デバッグを有効にするために、セキュアカーネルはデバッグ可能なエンクレーブモジュールに適用されるいくつかの例外を実装しています。たとえば、このようなモジュールのメモリーからの読み取りを試みると、通常のカーネルは SkmmDebugReadWriteMemory セキュアカーネル呼び出しを実行し、対象のモジュールが実際にデバッグ可能であることを確認したうえで、要求された操作を実行します。

この例を図 6 に示します。デバッグ可能なエンクレーブモジュールをロードすると、デバッガーはエンクレーブメモリーから正常に読み取ることができます。

この例を図 6 に示します。デバッグ可能なエンクレーブモジュールをロードすると、デバッガーはエンクレーブメモリーから正常に読み取ることができます。 図 6:エンクレーブモジュールがデバッグ可能な場合の図 5 と同じアドレスからの正常な読み取り

同様に、デバッグ可能なエンクレーブモジュール内のメモリー権限は VTL0 プロセスで変更できます( SkmmDebugProtectVirtualMemory セキュアカーネル呼び出しに実装されている例外)。

エンクレーブの核心的な目的である VTL0 からのメモリーの分離が損なわれるため、Microsoft では、開発者にデバッグ可能なエンクレーブモジュールを出荷しないよう強く呼びかけています(図 7)。デバッグ可能なモジュールを使用すると、そのモジュールで処理されるデータが簡単に公開される可能性があります。

エンクレーブの核心的な目的である VTL0 からのメモリーの分離が損なわれるため、Microsoft では、開発者にデバッグ可能なエンクレーブモジュールを出荷しないよう強く呼びかけています(図 7)。 図 7:デバッグ可能なエンクレーブモジュールに関する Microsoft の推奨事項(出典:https://learn.microsoft.com/en-us/windows/win32/trusted-execution/vbs-enclaves-dev-guide#:~:text=Step%204%3A%20Debugging%20VBS%20enclaves)

デバッグ可能なエンクレーブモジュールを実行する本番アプリケーションのリスクは明らかですが、攻撃者は実際、未署名のコードを VTL1 で実行するという別の目的のためにそれらを悪用する可能性があります。 デバッグ可能な署名済みエンクレーブモジュールを 1 つでも 取得した攻撃者は、次の 4 つのステップに従って VTL1 コードを実行できます。

  1. エンクレーブモジュール内のルーチンのアドレスを取得する GetProcAddress
  2. ルーチンメモリー保護を RWX に変更する
  3. ルーチンコードを任意のシェルコードで上書きする
  4. ルーチンをトリガーする CallEnclave

図 8 に、このプロセスを実装するコードを示します。

図 8 に、このプロセスを実装するコードを示します。 図 8:エンクレーブ内で未署名シェルコードを実行するコード例

攻撃者の視点から見た明らかな問題は、これが両刃の剣であることです。攻撃者がエンクレーブメモリーにアクセスできるのと同様に、EDR もアクセスできるからです。とはいえ、これには API 監視を回避できるという利点があります。エンクレーブモジュールによって実行される API コールは依然として VTL1 DLL とセキュアカーネルを経由し、EDR の可視性が制限されます。

全体的に、この手法は、エンクレーブ内で実行することによって得られるいくつかの利点を活かした、ステルス性の高い「semi-VTL1」インプラントを作成する場合に役立つかもしれません。

私たちは、VirusTotal などの情報源を使用して、デバッグ可能な署名付きエンクレーブモジュールを特定しようとしましたが、執筆時点ではうまくいっていません。しかし、十分に時間が経ち、エンクレーブテクノロジーが普及してくれば、最終的に何らかのモジュールが流出するのは間違いないでしょう。

脆弱なエンクレーブの持ち込み

ここまで説明したように、Windows は署名を使用して、信頼されていないエンクレーブが VTL1 にロードされるのを防いでいます。このアプローチはエンクレーブ特有のものではありません。この概念は、信頼されていないドライバーが Windows カーネルで実行されるのを防ぐ ドライバー署名の強制 (DSE)を通じて生まれました。

この強制を回避するために、攻撃者は 脆弱なドライバーの持ち込み (BYOVD)技術を使用し始めました。つまり、攻撃者は自分のドライバーをロードできないため、既知の脆弱性を持つ、正規の署名済みドライバーをロードします。次に、攻撃者はこの脆弱性を悪用することで、カーネルで未署名コードを実行することができます。

私たちはこの方法を、エンクレーブの観点から詳しく調査したいと考えました。つまり問題は、脆弱な署名済みエンクレーブモジュールを悪用して IUM でコードを実行できるのかということです。

最初のステップは、このようなエンクレーブを見つけることでしたが、すぐに CVE-2023-36880 に行き着きました。これは、Microsoft Edge が使用する VBS エンクレーブモジュールの脆弱性です。この脆弱性により、攻撃者はエンクレーブ内の任意のデータを読み書きすることができます。この脆弱性は、Microsoft によって情報漏洩の脆弱性として評価されましたが、注には、限定的なコード実行の可能性があることも示されています(図 9)。

この脆弱性は、Microsoft によって情報漏洩の脆弱性として評価されましたが、注には、限定的なコード実行の可能性があることも示されています(図 9)。 図 9:コードの実行につながる可能性があることを示す、CVE-2023-36880 の Microsoft パッチノート

この脆弱性は、Chrome セキュリティチームの Alex Gough 氏によって発見され、同氏は、悪用のための 概念実証 も共有しました。このエンクレーブの脆弱なバージョンを VirusTotalで見つけた後、私たちはこの脆弱性を悪用したコードの実行を開始しました。

当初は、読み取り/書き込みプリミティブを悪用して、エンクレーブスタックを ROP チェーンで上書きすることで、最終的にエンクレーブ内でシェルコードを実行できるようになると考えていました。このオプションを検討している間に、興味深い事実に遭遇しました。つまり、エンクレーブは Arbitrary Code Guard(ACG)を使用して、未署名のコードが実行されないように保護されているということです。

ACG は、動的に生成されたコード(元のプロセス実行可能ファイルや DLL の一部ではなく、実行時に作成されたコード)の実行をブロックするように設計されたセキュリティの緩和策です。ACG は、次の 2 つのルールを適用して実装されています。

  1. プロセスの初期ロード後に、新しい実行可能ページを生成することはできない
  2. 既存の実行可能なページは書き込み可能にできない

ACG は通常のカーネルではデフォルトで適用されますが、ユーザーモードでは、使用するように設定されたプロセスにのみ適用されます。調査により、エンクレーブを含む IUM プロセスでは、ACG は通常のカーネルと同様に自動的に適用されることがわかりました。

これは、VirtualAlloc を使用して、領域内に新しい RWX ページの割り当てを試みることで確認できます。この操作は、エラーコード 0x677 STATUS_DYNAMIC_CODE_BLOCKED で失敗します(図 10)。VirtualProtect を使用して実行可能ページの権限を変更したり、ページの実行可能ファイルを変更したりしようとすると、同じ結果になります。

これは、VirtualAlloc を使用して、エンクレーブ内に新しい RWX ページの割り当てを試みることで確認できます。この操作は、エラーコード 0x677、STATUSE_DYNAMIC_CODE_BLOCKED で失敗します(図 10)。 図 10:エンクレーブ内での RWX ページ割り当ての試み

この動作を理解するためには、 SecureKernel!NtAllocateVirtualMemoryExを調べます。これは、IUM の動的メモリー割り当てを処理するセキュアカーネル関数です。この関数は要求された保護マスクを評価し、実行可能ページが要求された場合は ACG エラー STATUS_DYNAMIC_CODE_BLOCKEDが返されます。既存の IUM ページへの変更を防止するために、同様のチェックが SkmmProtectVirtualMemory に実装されています(図 11)。

既存の IUM ページへの変更を防ぐため、SkmmProtectVirtualMemory にも同様のチェックが実装されています(図 11)。 図 11:NtAllocateVirtualMemoryEx のコードが実行可能メモリー割り当てを拒否する

エンクレーブ内で ACG をバイパスし、未署名コードをそのコードにロードする方法は見つかりませんでした。理論的には、完全な ROP 攻撃が可能であり、攻撃者が VTL1 で任意の API を呼び出すことができる可能性がありますが、この方向は追求していません。それでも、脆弱なエンクレーブの別の興味深い用途を特定することはできました。この用途については、 この記事の後半で説明します。

エンクレーブ内で実行に成功した攻撃者はどのような手法を使用するのか

エンクレーブには悪意のあるアクティビティが発生する可能性が多く、動機のある攻撃者であればそれを起動することも可能であると理解したうえで、次に取り組んだ問題は、この種のマルウェアにどのような手法が利用可能かということでした。

最も簡単なのは、エンクレーブを本来の使用目的に従うことです。エンクレーブが攻撃者から機密データを保護できるのと同様に、攻撃者は自身の「秘密」を VTL0 エンティティから隠して使用することができます。

これは、ペイロードを EDR の範囲外に保存したり、暗号化キーをアナリストから隠したり、機密性の高いマルウェア設定をメモリーダンプから除外したりするなど、多くのシナリオで役立ちます

より高度なオプションに関しては、従来のマルウェア技術の多くは、エンクレーブ内では実装できません。エンクレーブはシステム API の限られたサブセットしか使用できないため、ファイル、レジストリ、ネットワーク、その他のプロセスなどの主要な OS コンポーネントとは相互作用できません。

それにもかかわらず、エンクレーブ内で実行可能な技術はいくつか存在し、IUM で動作することによる利点を活かすことができます。

VTL0 ユーザー・モード・メモリーへのアクセス

システムへのアクセスは制限されていますが、エンクレーブは依然として 1 つの重要なリソース、つまりプロセスメモリーにアクセスできます。エンクレーブは、VTL0 を含むプロセスアドレス空間全体で読み取り/書き込み操作を実行できます。

このアクセスには、いくつかの制限が適用されています。エンクレーブ内で実行されるコードはメモリーのアクセス許可に準拠し、それを変更することができません。つまり、エンクレーブは書き込み不可能なメモリーに書き込むことも、実行不可能なメモリーの実行可能ファイルを変更することもできません。図 12 は、エンクレーブ内で実行されるコードを示しており、これらのさまざまな可能性と制約を示しています。

図 12 は、エンクレーブ内で実行されるコードを示しており、これらのさまざまな可能性と制約を示しています。 図 12:エンクレーブから VTL0 メモリーへのアクセスシナリオを示すコード例

VTL0 ユーザー・モード・メモリーにアクセスすることで、さまざまな有用な技術を実装できます。 悪意のあるエンクレーブをターゲットプロセスにロードすることで、こっそりと機密情報を監視して盗むことも、プロセス内の値を修正して、その動作を変更することもできます

エンクレーブを使用してこれらの手法を実装することには大きな利点があります。前述のように、エンクレーブから API をトリガーすることで、EDR の監視を回避できます。これらの手法のメモリーアクセスはエンクレーブによって実行されるため、検出されないままの可能性があります。

VTL0 ユーザー・モード・コードの実行

エンクレーブは、適切な権限を与えられた VTL0 ユーザー・モード・メモリーから読み取り/書き込みを行うことができますが、VTL0 に保存されたコードは、実行権限を持っていてもエンクレーブ内では実行できません。

エンクレーブ内で VTL0 コードを実行できないにもかかわらず、エンクレーブにはそれを「リモート」トリガーするオプションがあります。VTL0 アドレスを指定した CallEnclave API を使用することで、エンクレーブは通常のユーザー・モード・スレッドで VTL0 コードの実行をトリガーできます(図 13)。 

CallEnclave API を VTL0 アドレスとともに使用することで、エンクレーブは通常のユーザー・モード・スレッドで VTL0 コードの実行をトリガーできます(図 13)。 図 13:VTL0 コードの実行に失敗したエンクレーブを示すコード例

ユーザー・モード・プロセスを「代わりに動作」させることで、エンクレーブは通常は不可能な方法でシステムに間接的にアクセスできます。たとえば、エンクレーブは、ファイルからの読み取り、ソケットの作成などを行う VTL0 ルーチンをトリガーすることができます。

ただし、この方法でユーザー・モード・コードを実行しても回避の面での利点はありません。コードは他のユーザー・モード・コードと同様に実行されるため、EDR に検出される可能性があります。

アンチデバッグ

エンクレーブマルウェアのもう 1 つの興味深い用途は、アンチデバッグです。エンクレーブ内で実行されているコードは、デバッガーを含む VTL0 アプリケーションからアクセスできないため、マルウェアにはそれらに対して大きな優位性が与えられます。

エンクレーブに公開される API の数が減少したことは、従来のすべてのアンチデバッグ技術がエンクレーブから利用できるわけではないことを意味します。たとえば、 NtQueryInformationProcessIsDebuggerPresent API、およびすべての日時 API はエンクレーブでは使用できません。これにもかかわらず、いくつかの選択肢があります。

まず、プロセスの VTL0 アドレス空間へのエンクレーブのアクセスを利用して、プロセス PEB を手動で読み取り、BeingDebuggedフラグの値を確認することができます。デバッガーが検知された場合、プロセスはエンクレーブで終了できます。

もう 1 つのアプローチは、時間ベースのアンチデバッグ技術を実装することです(図 14)。エンクレーブでは日時 API を使用できませんが、 rdtsc アセンブリ命令を使用することはできます。この命令は、起動時からのプロセッサー・クロック・サイクル数を返します。これを使用して、異なるエンクレーブ呼び出し間の所要時間を測定し、大きな遅延が検知された場合はプロセスを終了することができます。

もう 1 つのアプローチは、時間ベースのアンチデバッグ技術を実装することです(図 14)。 図 14:rdtsc アセンブリ命令を使用したエンクレーブ内の時間ベースのアンチデバッグ

コードの重要な部分とアンチデバッグチェックをエンクレーブに移動することで、 動的な分析にほぼ完全に対応するマルウェアを作成できます。 マルウェアは正常に動作するためにエンクレーブを必要とし、ユーザー・モード・プロセスでは内部で実行されているチェックを修正することはできません。正しく実装されている場合、このアプローチは Hyper-V またはセキュアカーネルのデバッグによってのみ無効にできます。

BYOVE — ラウンド 2

前のセクションでは、IUM でコードを実行するために、脆弱なエンクレーブモジュールの悪用を試みました。これが不可能かもしれないとわかったとき、私たちは、BYOVE の概念に他の用途があるかどうかを確認し、脆弱なエンクレーブモジュールをさらに調査することにしました。

脆弱性(CVE-2023-36880)は、 SealSettingsUnsealSettings 関数に起因します。これらは、 エンクレーブモジュールにエクスポートされます。 SealSettings 関数は、データバッファへのポインターを受け取り、それを暗号化し、結果を呼び出し側から提供された宛先アドレスに書き込みます。 UnsealSettings は同様の方法で動作し、指定されたバッファを復号して、指定されたアドレスに書き込みます。

これら 2 つの関数の問題点は、宛先アドレスも送信元バッファアドレスのいずれも検証せず、プロセス内の任意のアドレスを指すことができることです。 これには、エンクレーブ自体の内部アドレスも含まれますにエクスポートされます。図 15 は、脆弱なコードを示しています。UnsealSettings は、ユーザーが指定した任意のアドレスに対して memcpy を実行しています。

図 15 は脆弱なコードを示しています(ユーザーが指定した任意のアドレスに memcpy を実行する UnsealSettings)。 図 15:UnsealSettings 関数内の脆弱なコード

この脆弱性は、攻撃者に 2 つの機能を提供します(図 16)。

この脆弱性は、攻撃者に 2 つの機能を提供します(図 16)。 図 16:エンクレーブ内の任意のデータを読み書きするために CVE-2023-36880 を悪用する
  1. エンクレーブ内での任意の書き込み:攻撃者は SealSettings を呼び出して任意のデータを暗号化してから、 UnsealSettings を呼び出して、エンクレーブ内の宛先アドレスを指すことができます。これにより、元のデータがエンクレーブメモリーに書き込まれます。

  2. エンクレーブ内での任意の読み取り:攻撃者は SealSettingsを呼び出すと同時に、エンクレーブ内のアドレスを送信元バッファポインターとして指定します。これにより、エンクレーブはエンクレーブメモリーからデータを暗号化し、攻撃者が制御する場所に書き込みます。攻撃者は、その後 UnsealSettingsを呼び出してこのデータを復号化し、エンクレーブからの任意のデータを読み取ることができます。

Mirage:VTL1 ベースのメモリー回避

VTL1 でコードを実行することはできませんでしたが、任意の書き込みプリミティブによって、次の 2 つの独自の機能が提供されます。 

  1. VTL1 に任意のデータを保存し、VTL0 エンティティからアクセスできなくする

  2. 通常のプロセスアドレス空間(VTL0)に VTL1から任意のデータを書き込み、VTL0 エンティティがこの操作を監視できないようにする

さらに、これらの機能は署名済みエンクレーブモジュールをロードすることで実現されるため、 攻撃者に利用される可能性があります。攻撃者自身が署名を行う必要はありません。

これらの機能の可能性を示すために、私たちは、メモリースキャン回避技術を考案して「Mirage」と名付けました。Mirage は、無害な状態と武器化された状態を継続的に切り替えるペイロードを作成する回避技術である Gargoyleからヒントを得ています(図 17)。

Mirage は、無害な状態と武器化された状態を継続的に切り替えるペイロードを作成する回避技術である Gargoyle からヒントを得ています(図 17)。 図 17:Mirage メモリー回避

Gargoyle は、実行可能メモリーと実行不可能メモリーを切り替えることでこれを実装していますが、Mirage は VTL1 と VTL0 メモリー間を移行することで同様の結果を達成することを目指しています。VTL1 エンクレーブメモリーにシェルコードを保存し、定期的に VTL0 に転送して実行し、VTL0 メモリーからすぐに消去します(図 18)。

このプログラムは、VTL1 エンクレーブメモリーにシェルコードを保存し、脆弱性を使用して定期的に VTL0 に転送し、実行した後、VTL0 メモリーから即座に消去します(図 18)。 図 18:Mirage 回避プロセスのライフサイクル

このアプローチには主に 2 つの利点があります。まず、ペイロードはほとんどの時間を VTL1 に隠れて過ごすため、メモリースキャンやダンプに対して耐性があります。これは、Gargoyle 技術よりも有利です。なぜなら、休止段階では、ペイロードは「ステルス性がある」だけでなく アクセスできないからですにエクスポートされます。

2 番目の利点は、VTL0 へのシェルコードの書き込みがエンクレーブによって実行されることです。前述したように、EDR は VTL1 で実行されるコードを監視できません。つまり、通常の EDR フックでは、シェルコードがメモリーに書き込まれている際に、それを傍受できません。

私たちは Mirage の POC を開発しました(図 19)。この PoC は、この手法の背景にあるアイデアを実証するためだけのものであり、完全に武器化されたものではありません。

私たちは Mirage 用の PoC を開発しました(図 19)。 図 19:Mirage の実行デモ

検出

現在、エンクレーブは非常に限られた数のアプリケーションで使用されています。より広く採用されるようになったとしても、任意のプロセスではなく、特定のプロセスによってのみロードされるでしょう。たとえば、 calc.exe が VBS エンクレーブをロードすることはないでしょう。

このため、異常なエンクレーブを使用することで検出される可能性が大きく高まります。防御者は、VBS エンクレーブの既知の合法的な使用のベースラインを構築し、それからの逸脱をフラグすることで、これを活用する必要があります。エンクレーブの使用は、エンクレーブ API を監視し、ロードされたエンクレーブ DLL を検知するという 2 つの方法で識別できます。

エンクレーブ API

次の API は、ホストプロセスによって VBS エンクレーブを管理するために使用され、ロードされていることを示している可能性があります。

  • CreateEnclave
  • LoadEnclaveImageW
  • InitializeEnclave
  • CallEnclave
  • DeleteEnclave
  • TerminateEnclave

ロード済み Enclave DLL

異常なエンクレーブの使用を検知するもう 1 つのオプションは、それらによって一般的に使用される環境 DLL( Vertdll.dllucrtbase_enclave.dllにエクスポートされます。これらの DLL はエンクレーブ以外では使用できないため、プロセスでエンクレーブが使用される可能性が高いことを示します。

結論

VBS エンクレーブは、開発者がアプリケーションの機密性の高いセクションを保護するための優れたツールを提供しますが、これまでに示したように、脅威アクターがマルウェアを「保護」するために使用することもできます。この概念はほとんど理論上のものですが、将来、高度な脅威アクターが悪意のある目的で VBS エンクレーブを使用し始める可能性は確かに存在します。 

謝辞

最近、このプロジェクトと非常に類似した研究プロジェクトを行った Offsec の Matteo Malvica 氏と Outflank の Cedric Van Bockhaven 氏の取り組みに感謝の意を表します。2 部構成の連載の 第 1 部のブログ記事 もご覧ください。第 2 部は、 Insomni’Hack 2025 の後に公開予定ですので、お楽しみに



Ori David

執筆者

Ori David

February 25, 2025

Ori David

執筆者

Ori David

Ori David は、Akamai の Security Researcher です。彼は、オフェンシブセキュリティ、マルウェア分析、脅威ハンティングに焦点を当てた調査を行っています。