VMware Workstation のレンダラーの脆弱性の調査

VMware Workstation のレンダラーの脆弱性の調査

[[214684]]

背景

1月中旬、ZDIは2017年のコンテストのルールを発表した。そのルールにはVMwareへの侵入が含まれており、仮想マシンからの脱出を成功させたチームには非常に高額の賞金が贈られる予定だ。 VMware は新しいターゲットではありません。 VMware は 2016 年に標的として特定されました。

VMware は、ターゲットとして、多くの攻撃ポイントを持つさまざまな攻撃を経験してきました。

興味深いことに、仮想マシンからの脱出は、2006 年から 2009 年にかけて、D&D と C&P の脆弱性を悪用して実現されていました。しかし、2015 年に Kostya Kortchinsky 氏と lokihardt 氏が D&D と C&P に同様の脆弱性を発見しました。それ以来、研究者たちはこれらのコードをより深く研究し始めました。

傍観者である私たちの視点から見ると、この現象は考えさせられるものです。 VMware には脆弱性がいくつあるのでしょうか?どれを発見できるでしょうか?

一連の脆弱性が明らかになったにもかかわらず、Pwn2Own 2016 ではどのチームも仮想マシンから脱出できませんでした。VMware のような従来のデスクトップ ソフトウェアは私たちの研究分野ではありません。しかし、私たちは依然として VMware の脆弱性を見つけることに非常に興味を持っています。

私たちはこの挑戦に取り組み、VMware の脆弱性を見つけることがいかに難しいかを確認することにしました。私たちは、空き時間を1か月かけて脆弱性を探す計画を立てました。 Pwn2Own の前に完了することはできませんでしたが、いくつかの高リスクの脆弱性を発見し、これらの脆弱性を通じて VMware で悪用可能な攻撃ポイントを見つけようとしました。

攻撃対象領域

VMware の詳細を知らなかったため、当初はどこから攻撃を開始すればよいかわかりませんでした。命令シミュレーションの内部詳細に焦点を当てることは役立ちますか?一部の CPU は VT をサポートしていますが、いくつの命令がエミュレートされますか?他の人とのトラブルを避けるために、D&D や C&P などのホスト クライアントで印刷してやり取りする以外に何ができるでしょうか?

以下は私たちの研究結果です。 Pwn2Own で規定されているように、すべての脆弱性は仮想マシン内の一般ユーザーによって悪用可能でなければなりません。

VMWare モジュール

VMware のさまざまなモジュールの中で、GUI は最も関心の薄い部分です。 VMware には、ホスト側と仮想マシン側の両方にカーネル モジュール (少なくとも vmnet/VMCI)、thnuclnt (仮想印刷を担当)、vmnet-dhcpd、vmnet-natd、vmnet-netifup、vmware-authdlaucher、vmnet-bridge、vmware-usbarbitrator、vmware-hostd、そして仮想マシン側で最も重要な vmware-tools があります。

これらのモジュールのほとんどは特権プロセスとして実行されるため、研究者による分析の魅力的なターゲットとなります。仮想印刷は何度も攻撃を受けています。

vmnet-dhcpd はルート モードで実行され、ISC-DHCPD から派生したものであるため、注目を集めました。さらに興味深いのは、vmware-dhcpd が isc-dhcp2 に基づいていることです。私たちはそれをターゲットにし始めました。

しかし、公開された脆弱性 (CVE-2011-2749、CVE-2011-2748) を発見した後、このアイデアは断念しました。この脆弱性を防ぐために、VMware は最新の isc-dhcp の脆弱性を修正しました。

私たちは、QEMU と AFL で vmware-dhcpd のいくつかの小さなパッチをファジングすることにしました。 1 か月のファジングでは脆弱性は発見されませんでした。 vmware-hostd も、仮想マシン共有用の Web サーバーとして機能し、仮想マシン内からアクセスできる興味深いプロセスです。しかし、私たちは VMware のコア コンポーネントに注力することにしました。

vmware-vmx は、ホスト上でルート/システム プロセスとして実行されるメインの仮想マシン監視モジュールであり、いくつかの興味深い機能を備えています。実際、vmware-vmx と vmware-vmx-debug の 2 つのバージョンがあります。

後者は、VMware の設定でデバッグ オプションが有効になっている場合に使用されます。これは、リバース エンジニアリングを行うときに、デバッグ情報が豊富なバージョンから開始する方が常に簡単であるため重要です。これは最も適切なアプローチではないかもしれませんが、機能します。それについては後で話しましょう。

RPC/RPCI

VM とホスト間のファイルのドラッグ アンド ドロップ機能がどのように実装されているのか疑問に思ったことはありませんか? RPC はこの点で重要な役割を果たします。 VMware は内部的にポート 0x5658 のインターフェースを「バックドア」として提供しています。このポートを通じて、仮想マシンは I/O 命令を通じてホストと通信できます。

VMware がレジスタを通じて認識できるマジックナンバーを渡すと、VMware は追加のパラメータを自動的に解析します。 I/O 命令は通常は特権命令ですが、この「バックドア」インターフェースは例外です。このような例外はまれです。バックドア I/O 命令が実行されると、VMware は一連のチェックを実行して、I/O 命令が特権を持つ仮想マシンからのものであるかどうかを判断します。

VMware は、この「バックドア」インターフェース上で、RPC サービスを使用してホストとクライアント間でデータを交換します。クライアント側では、vmware-toolsd は「バックドア」コマンドを実行するときに RPC サービスを使用します。

そのため、後でゲスト上でファイルのドラッグ アンド ドロップなどの機能を使用できるのは、vmware-toolsd がインストールされている場合のみです。この機能は、カーネル ドライバーとユーザー スペース関数の組み合わせによって実現されます。

元の「バックドア」インターフェースでは、データはレジスタを介してのみ転送でき、大量のデータを送信する場合、速度が非常に遅くなります。この問題を解決するために、VMware は高帯域幅の「バックドア」を実装するための別のポート (0x5659) を導入しました。実際にはこのポートは RPC によって使用されます。

データ ポインタを渡すことで、vmware-vmx は IN 命令を繰り返し呼び出す必要がなくなり、読み取り/書き込み API を直接呼び出してデータ転送を完了できます。デレクはかつてこの機能に非常に興味深い脆弱性を発見しました。

RPC インターフェイスは次の機能を提供します。

  • オープンチャンネル
  • 送信コマンドの長さ
  • データの送信
  • 許容される応答の長さ
  • データの受け入れ
  • やり取りを終了する
  • チャネルを閉じる

プロセスが RPC のやり取りを妨害するのを防ぐにはどうすればよいか疑問に思うかもしれません。チャネルが確立されると、VMware はデータの送受信に使用される 2 つの Cookie 値を生成します。どうやら、これら 2 つの Cookie は安全な方法で生成されているようです。これら 2 つの Cookie は単なる 2 つの 32 ビット符号なし整数であるため、memcmp やその他の方法を使用して比較することはできません。

上位レベルでは、VMware は RPC コマンドを使用して、DnD、CnP、Unity などのイベントも処理します。一部のコマンドは、仮想マシンの特権ユーザーのみが実行できます。仮想マシン側。 vmware-tool または open-vm-tools は、API と対話するための rpctool を提供します。仮想マシン情報を保存および取得する簡単な例は次のとおりです。

  1. rpctool 'info-set guestinfo.foobar baz'  
  2. rpctool 'info-get guestinfo.foobar' -> baz

情報を vmware-vmx に保存し、後で抽出します。データの保存方法の詳細については、この記事では説明しません。 VMware は内部的に VMDB を使用します。これは、特定のデータに対するコールバック関数を提供するキーワード保存データベースです。

ただし、権限のない VM で呼び出すことができる RPC コマンドの数には制限があります。 RPC コマンドの完全なリストはバージョンとオペレーティング システムに依存するため、提供することはできません。コマンド リストを取得する最も簡単な方法は、メモリからコマンド リストをダンプすることです。

幸いなことに、vmware-vmx の Linux バージョンではシンボルが提供されており、簡単に入手できます。

最も興味深い攻撃ポイントは、D&D、C&P、Unity です。しかし、私たちは2つの理由でそれを研究しませんでした。まず、lokihardt はすでに Pwnfest でこれをうまく利用しています。さらに重要なことは、Pwn2Own2016 では、Unity および仮想印刷のエクスプロイトは許可されていないことです。

この潜在的なリスクのため、2017 年には VMware と ZDI が分離設定に関連しない VM エスケープに対してより関心を持つようになると予想されます。 Pwn2Own 2017 では競技ルールの詳細は明らかにされていませんが、私たちは潜在的なリスクを負うつもりはありません。最終的に、RPC の脆弱性を悪用しないことに決定しました。

ただし、RPC にはヒープ メモリを操作する機能があるため、攻撃によって悪用される可能性のあるポイントが多数あることには注意が必要です。

周辺機器の仮想化

他に攻撃ポイントはありますか? VMware のコア コードは命令仮想化を実装し、クライアントにさまざまな仮想周辺機器も提供します。これらのデバイスには、ネットワーク、USB、Bluetooth、ハードディスク、イメージ インターフェイスなどが含まれます。

ユーザー スペース サービス、仮想マシン カーネル ドライバー、および vmware-vmx が連携して、仮想化デバイスにサービスを提供します。たとえば、VMware は、PCI ディスプレイ デバイス ドライバーとして仮想マシン内に SVGA グラフィック カード アダプターを提供します。

Linux では、vmwgfx カーネル モジュールの X コードを変更して、vmware-vmx で SVGA3D/2D のインターフェイス レイヤーを確立します。最新のオペレーティング システムでデフォルトで有効になっている仮想化された周辺機器は、大きな攻撃対象領域となると考えられます。そのため、私たちはデフォルトで有効になっていて、攻撃対象領域が広く、ファジング可能なモジュールを探しています。最終的にグラフィカルインターフェースを選択しました。

レンダラーの脆弱性を見つける

競争プラットフォームは Windows 10 上の VMware Workstation であったため、Linux ではなく Windows 上のグラフィカル インターフェイスを調査することにしました。 Gallium の svga コードにおける VMware グラフィック ドライバーのオープン ソース実装が、vmware-vmx の関連部分の分析に大いに役立ったことは特筆に値します。同様に、Microsoft のグラフィックス デバイス ドライバー ルーチンも、Windows ドライバーの動作を理解するのに非常に役立ちます。

これまでにも SVGA コマンドが攻撃されたことはありましたが、私たちはさらに深く調査し、この複雑なモジュールの特定の機能、つまり GPU レンダラーの変換モジュールの脆弱性を探すことにしました。 SVGA コマンドの代わりにレンダラー バイトコードを選択する重要な理由は、レンダラー バイトコードを仮想マシン内から提供できることです。

Linux および Mac では、レンダラーは OpenGL として実装されています。 Windows では、これは Direct3D を使用して実装されます。 VMware はさまざまな仮想マシン オペレーティング システムをサポートする必要があるため、さまざまなレンダラーのコードをホスト上のレンダラーの動作に変換する必要があります。このような非常に複雑なモジュールでは、さまざまな脆弱性が生じると考えられます。

当社の最初の分析は VMware Workstation 12.5.3 に基づいて行われました。

建築

VMware には 2 つの GPU 実装があります。 1 つは VGPU9 (DirectX 9.0 に相当) で、Linux 仮想マシンおよび古いバージョンの Windows 仮想マシンで使用されます。もう1つは、Windows 10で使用されるVGPU 10です。

3D アクセラレーション グラフィック インターフェイスの場合、VMware は Windows 10 仮想マシンで WDDM (Microsoft Display Driver Model) ドライバーを使用します。このドライバーは、ユーザー部分とカーネル部分で構成されています。ユーザー部分は vm3dum64_10.dll で、カーネル部分は vm3dp.sys です。 Direct 3D レンダラーを使用する場合、バイトコードは複数の変換を経ます。

VMware は仮想 3D サポートを提供しているため、これらのバイトコードを直接使用することはできません。これらはさらに翻訳され、Direct 3D API は対応するレンダラー実装を使用する必要があります。したがって、ユーザー空間ドライバーは、D3D10DDI_DEVICEFUNC 構造体に格納されているコールバック関数を実装します。バイトコードを対応する API に変換します。

この場合、VMWare SVGA3D は API を定義し、レンダラーを設定します。レンダラー バイトコードを処理する際に、ユーザー空間ドライバーはカーネル ドライバーによって提供される pfnRenderCB コールバック関数を呼び出します。

GPU レンダラーを必要とする Windows プログラムはすべて、Windows D3D11 API を使用する必要があります。これらの API は、ファイル内のレンダラー バイトコードを変換し、さまざまなタイプのレンダラーに設定する役割を担います。一般的な翻訳プロセスを下の図に示します。

このプロセスには、他の多くの詳細が含まれており、多数の D3D11 API が関係します。興味のある読者は、Microsoft が提供する Direct3D11 の例を確認し、Windbg を使用してトレースおよびデバッグすることができます。 (Windbgのwtコマンドを使用)

  1. 0:000> x /D /f チュートリアル03!i*
  2. A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
  3.   
  4. 00000000`00da1900 チュートリアル03!InitDevice (void)
  5. 00000000`00da28f0 チュートリアル03!InitWindow (struct HINSTANCE__ *, int )
  6. 00000000`00da3630 チュートリアル03!invoke_main (void)
  7. 00000000`00da3620 チュートリアル03!initialize_environment (void)
  8. 00000000`00da4680 チュートリアル03!is_potentially_valid_image_base (void *)
  9. 00000000`00da637a Tutorial03!IsDebuggerPresent (< パラメータ情報なし>)
  10. 00000000`00da63c8 Tutorial03!InitializeSListHead (<パラメータ情報なし>)
  11. 00000000`00da63aa Tutorial03!IsProcessorFeaturePresent (< パラメータ情報なし>)
  12. 0:000> bp チュートリアル03!デバイスの初期化
  13. 0:000> グラム
  14. ブレークポイント 0 ヒット
  15. チュートリアル03!デバイスの初期化:
  16. 00da1900 55 プッシュEBP
  17. 0:000:x86> wt -l 8
  18. トレースチュートリアル03!InitDevice 返送先住所 00da2dfe
  19. 259 0 [ 0] チュートリアル03!デバイスの初期化
  20. 100 0 [ 1] USER32!GetClientRect
  21. ...

レンダラー入力データの構築

VMware のレンダラーと対話する場合、レンダラーがどのように動作するかを理解することが重要です。

DirectX レンダラーを作成するには、High-Level Shading Language (HLSL) を使用する必要があります。 D3D11 API または fxc.exe プログラムを使用してバイトコードにコンパイルします。レンダラー モデルに応じて、HLSL はさまざまな種類のレンダラー機能を提供します。

HLSL コンパイル結果は、シェーダー モデルのアセンブリ バイトコードの形式で提供されます。 VMware は現在、SM3 と SM4 を内部的にサポートしていますが、SM5 と SM6 はサポートしていません。これは、vmware-vmx のリバース エンジニアリングにおける翻訳ユニットにとって重要です。

残念ながら、Windows プラットフォームでは、HLSL 以外にレンダラー バイトコードを生成するツールはありません。したがって、脆弱性をトリガーするための正確な入力を構築することは困難です。 CSO ファイルのチェックサムも修正する必要があります。検証値をチェックする関数はD3D11_3SDKLayers!DXBCVerifyHashです

VMware に任意のレンダラー バイトコード入力を提供するために、強力な Frida ツールを使用してレンダラー バイトコードをフックおよび変更しました。 vm3dum64_10.dll がコンパイルされたバイトコードをメモリに配置すると、入力したい任意のバイトコードに変更されます。リバースエンジニアリングを通じて、対応する memmove() の場所を特定し、それをフックしました。

以下は Frida コードの一部です。

  1. var vm3d_base = Module.findBaseAddress( "vm3dum64_10.dll" );
  2. console.log( "ベースアドレス: " + vm3d_base);
  3.   
  4. 関数ida2win(addr) {
  5. var idaBase = ptr( '0x180000000' );
  6. var off = ptr(addr).sub(idaBase);
  7. var res = vm3d_base.add (オフ) ;
  8. console.log( "翻訳済み " + ptr(addr) + " -> " + res);
  9. resを返します
  10. }
  11.   
  12. 関数開始() {
  13. var memmove_addr = ida2win(0x180012840);
  14. var setShader_return = ida2win(0x180009bf4);
  15.   
  16. インターセプター.attach(memmove_addr, {
  17. onLeave:関数(戻り値) {
  18. もしこれがヒットしたら
  19. 戻る;
  20. }
  21. Memory.writeU32( this.dest_addr.add (...),...);
  22. ....
  23. },
  24. onEnter:関数(引数) {
  25. var shaderType = Memory.readU8(args[1] .add (2));
  26. if (!this.returnAddress.compare(setShader_return)) {
  27. シェーダータイプが 1 の場合、戻り値は; }
  28. this.dest_addr = args[0];
  29. this.src_addr = args[1];
  30. this.len = args[2].toInt32();
  31. this.hit = 1;
  32. ...
  33. });
  34. }

上記のコードは、Frida を使用して、vm3dum64_10 の memmove() の制御フローをハイジャックします。コードが memmove() に入るたびに、戻り値が setShader() と比較されます。同じ場合は、memmove() を終了する前にメモリ内のバイトコードを変更します。

私たちの調査中に、Marco Grassi 氏と Peter Hlavaty 氏が発表したレンダラー ファジングについて学んだことは注目に値します。 VMware はレンダラー ツールキットといくつかの例を提供していると記載されています。これが彼らのファジング研究の基礎であり、彼らの研究結果はここで見ることができます。

脆弱性の発見

VMware は巨大なソフトウェアであり、vmware-vmx からレンダラー変換機能を識別する方法がわかりません。方法は 2 つしかありません。1 つは、レンダラーの翻訳単位を直接識別することです。 2 番目は、SVGA3D コマンド処理関数を使用するもので、通常は次のようになります: DXDDefine、DXBindShader、DefineSurface。

バイナリ ファイル内の文字列を見つけるのは比較的簡単です。次の図は、SVGA3d コマンドで使用される文字列を示しています。

これらの文字列は対応する処理関数を直接見つけることはできませんが、X 参照を通じてメモリ内の別のテーブルを見つけることができます。

文字列テーブル内のオフセットでマークすることで、直接処理関数を見つけることができます。これらは最終的にはレンダラーの動作を制御するために使用されるため、これらの関数に従うと解析および変換コードにつながります。内部実装では、カーネル ドライバーと vmware-vmx は先入先出データ構造を使用して実装され、SVGA3D コマンドをスタックにプッシュしてスーパーバイザーに渡します。これらのモジュールはデータを取得してさらに処理します。

レンダラー コードを直接見つける方法は 2 つあります。最初のものは、vmware-vmx-debug 内の文字列を使用して、解析および変換コードを直接見つけます。まず、文字列「shaderParseSM4.c」と「shaderTransSM4.c」への相互参照をたどりました。しかし、デバッグ バージョンでのコードの脆弱性の監査には大きな欠陥があります。デバッグバージョンには、リリースバージョンでは利用できない多くのチェック機能があります。

vmware-vmx コードの監査中に、これが VMware の設計上の欠陥であるかどうかはわかりません。デバッグバージョンでは、解析モジュールと翻訳モジュールに厳格なセキュリティチェックが多数あります。リリースバージョンでは利用できません。

したがって、デバッグ バージョンで見つかった即時パラメータを使用して、非デバッグ バージョンでそれらを見つけます。これにより、IDA コードの読みやすさが大幅に向上します。 mesa ドライバーのおかげで、何を検索する必要があるかがわかりました。

たとえば、mesa ドライバーの VGPU10 の定義は、分析に非常に役立ちます。

vmware-vmx が仮想マシンのレンダラー コードをホストのレンダラー コードに変換する必要がある場合、まず仮想マシンの内部ライブラリ関数にパッケージ化されたレンダラー バイトコードを解析します。基礎となるレンダラー バイトコードに関する情報が不足していたため、解析関数を逆にしてさまざまな入力を構築するのに多くの時間がかかりました。

初期の解析プロセスは比較的単純で、ParserSM4() 関数はパラメータのみを保存します。

パーサーがバイトコードを解析する際の動作は、他のパーサーと同様です。レンダラー コードの長さは、パーサーが解析を停止するタイミングを通知します。各バイトコードには、タイプ、命令長、および値があります。具体的には、各バイトの末尾のビット 0:10 はバイトコードの種類を決定し、ビット 11:23 はバイトコード データをエンコードし、ビット 30:24 はバイトコード データの長さを記録し、ビット 31 はバイトコードが拡張されているかどうか (通常は拡張されていません) を記録します。

ほとんどのバイトコードには長さが 1 バイトの値が含まれているため、パーサーはこのバイトの値を不明なデータ構造にコピーします。上図のVGPU10_OPCODE_CUSTOMDATAは例外です。バッファが含まれているため、dcl_immediateConstantBuffer が記述されます。

前述のように、内部で使用されるデータ構造はわかりません。ただし、データ構造で使用されるオフセットは同じであるため、翻訳単位の脆弱性を見つける場合にはこれは問題になりません。したがって、入力バイトコードが何であるかがわかれば、TransSM4 のバイナリ コードを監査するのに便利です。

全体として、これはまだ非常に時間のかかるステップです。まず、レンダラーや VMware のグラフィック インターフェイス仮想化についてあまり知らなかったため、重要なポイントを見つけるのに時間がかかりました。第二に、sm4 バイトコードを直接生成するツールがないため、関数内でバイトコードを動的にフックするには Frida を使用することしかできません。

最後に、SM4 命令の詳細と原理を理解することも大きなプロジェクトです。デバッガーに加えて、リバース エンジニアリングに役立つツールもいくつかあります。 vmware-vmx のデバッグ バージョンの ASSERT アサーションは、ランタイム エラーを理解するのに役立ちます。

ParseSM4() 関数は、レンダラー バイトコードを抽出して VMware ログに記録するために使用できるレンダラー逆アセンブリ関数を提供します。

結果

それでは、手動のリバース エンジニアリングで見つかった結果のいくつかを見てみましょう。 2017 年 3 月 17 日、Pwn2Own で、これらの脆弱性と概念実証を ZDI に提出しました。

1. dcl_immediateConstantBuffer バイトコードを変換する際のヒープオーバーフロー

VGPU10_OPCODE_CUSTOMDATA というトークン (バッファを定義する) を解析すると、次の疑似コードが実行されます。

  1. VGPU10_OPCODE_CUSTOMDATAの場合:
  2. v41 = v23 >> 11;
  3. *(_DWORD *)(_out_p_16_ptr + op_idx + 16) = v41;
  4. ( (_DWORD)v41 == VGPU10_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER ) の場合
  5. {
  6. *(_DWORD *)(_out_p_16_ptr + op_idx + 32) = insn_l;
  7. custom_data_alloc = (void *)mksMemMgr_alloc(v41, 0x10009u, 4LL * (unsigned int )insn_l);// intオーバーフローセーフ
  8. *(_QWORD *)(_out_p_16_ptr + op_idx + 24) = custom_data_alloc;
  9. memcpy(custom_data_alloc, bc_tmp_ptr, 4LL * *(unsigned int *)(_out_p_16_ptr + op_idx + 32));
  10. 37 = 0;
  11. insn_start = ( int *)bc_tmp_ptr;
  12. }

この場合、insn_l はユーザー データ命令にエンコードされた 32 ビット定数を表します。通常、レンダラー命令は 32 ビット値を使用しないため、これは特殊なケースです。この数値はユーザー データ ブロックの長さを示します。コードではこの長さに制限はありません。

mksMemMgr_alloc は内部的に calloc を呼び出し、長さ 159384 のヒープ領域を割り当てます。calloc 関数は msvcr90.dll によって提供されます。 msvcr90.dll は常に 4G メモリの下部にマップされていることがわかりました。

Windows 10 の calloc 関数は、RtlAllocateHeap を介して NT ヒープ内にメモリを割り当てます。このメモリは、攻撃者によって完全に制御される outbuf で使用します。

このメモリを割り当てた後、変換フェーズは終了します。トークン VGPU10_OPCODE_COSTOMDATA に遭遇しました。 memcpy はそれ以上の安全性チェックなしで呼び出されます。

  1. 結果 = memcpy(outbuf + 106228, custom_data_alloc, 4 * len);

custom_data_alloc は、上記の解析手順で割り当てたバッファです。これにより、隣接するヒープ ブロックのヘッダーに慎重に作成されたデータを書き込むことができます。これらの隣接するヒープ ブロックは、以前に解析されたバイトコードであり、このメモリ領域も割り当てられます。

2. dcl_indexableTempバイトコードを変換する際にヒープ境界外書き込みの脆弱性が存在する

dcl_indexabletempディレクティブを処理する際、レンダラー解析モジュールは次の疑似コードを呼び出します。

  1. VGPU10_OPCODE_DCL_INDEXABLE_TEMPの場合:
  2. *(_DWORD *)(_out_p_16_ptr + op_idx + 16) = *insn_start;//インデックス 
  3. *(_DWORD *)(_out_p_16_ptr + op_idx + 20) = insn_start[1];// Trans配列書き込み操作インデックス+ 値
  4. bc_tmp_ptr = insn_start + 3;
  5. *(_DWORD *)(_out_p_16_ptr + op_idx + 24) = insn_start[2];

上記の疑似コードでは、命令の一部がop_idxに書き込まれており、これらの値は後続の変換モジュールで使用されます。解析中、これらの値に制限はありません。

次のコードは翻訳プロセスを示しています

  1. VGPU10_OPCODE_DCL_INDEXABLE_TEMPの場合:
  2. v87 = *(_DWORD *)(バイトコードptr + op_idx + 24);
  3.   
  4. svga3d_dcl_indexable_temp((__int64)__out,
  5. *(_DWORD *)(bytecode_ptr + op_idx + 16),// idx
  6. *(_DWORD *)(bytecode_ptr + op_idx + 20),// 値
  7. (1 << v87) - 1); // 値2

svga3d_dcl_indexable_temp() の呼び出しでは同じオフセット値 (20,16,24) が使用されていることがわかります。 idx と val は攻撃者によって直接制御されます。 4番目のパラメータは、上記の3番目のダブルワード演算によって取得されます((1<<val2)-1)

svga3d_dcl_indexable_temp()関数を入力します

  1. __int64 __fastcall svga3d_dcl_indexable_temp(__int64 a1、符号なし整数idx 整数val、 char val2)
  2. {
  3. __int64 結果; // ラックス@5
  4. 定数char *v5; // rcx@7
  5. 定数char *v6; // rsi@7
  6. 符号付き__int64v7; // rdx@7
  7. *(_DWORD *)(a1 + 8LL * idx + 0x1ED80) = 値;
  8. *(_BYTE *)(a1 + 8LL * idx + 0x1ED84) = val2;
  9. *(_BYTE *)(a1 + 8LL * idx + 0x1ED85) = 1;
  10. 結果 = idx;
  11. 結果を返します

上記のコードでは、a1 は変換プロセス中に使用されるヒープ ブロックであり、これは前に説明したユーザー データ ブロックと同じです。 0x1ed80 をベース アドレスとして使用すると、任意のオフセットに 32 ビットの DWORD 値を書き込むことができます。

要約すると、この脆弱性により、前述のヒープ構造内の任意のアドレスにダブルワード値を書き込むことが可能になります。 val によって制御される 2 バイトを書き込むこともできます (残りの 2 バイトは 0 です)。

3. dcl_resource バイトコードを変換する際のスタック境界外書き込みの脆弱性

変換中に dcl_resource ディレクティブが処理されると、次のコードが実行されます。

  1. intヒットミー[128]; // [rsp+1620h] [rbp-258h]@196
  2. 整数v144; // [rsp+1820h] [rbp-58h]@204
  3. 文字v145; // [rsp+1824h] [rbp-54h]@303
  4. ブールv146; // [rsp+1830h] [rbp-48h]@14
  5. 文字v147; // [rsp+1831h] [rbp-47h]@14
  6. 整数v148; // [rsp+1880h] [rbp+8h]@1
  7. __int64v149; // [rsp+1890h] [rbp+18h]@1
  8. __int64v150; // [rsp+1898h] [rbp+20h]@14
  9. ...
  10. VGPU10_OPCODE_DCL_RESOURCEの場合:
  11.   
  12. v87 = sub_1403C2200(*(_DWORD *)(v14 + 32));
  13. v88 = sub_1403C2200(*(_DWORD *)(v14 + 28));
  14. v89 = sub_1403C2200(*(_DWORD *)(v14 + 24));
  15. v90 = sub_1403C2200(*(_DWORD *)(v14 + 20));
  16. sub_1402FCF10(&v107、(__int64)outptr、*(_DWORD *)(v14 + 80)、v86、v90、v89、v88、v87);
  17. v11 = 0i64;
  18. hitme[(unsigned __int64)*(unsigned int *)(v14 + 80)] = *(_DWORD *)(v14 + 16);

sub_1403c2200() 関数の詳細については説明しませんでしたが、この関数はスタック構造に影響を与えないため重要ではありません。オフセット (v14+80) も、入力レンダラー バイトコードによって完全に制御されます。ただし、書き込まれる値には一定の制限があります。 0~31 までしか使えません。

これは、整列した二重単語を多数記述できることを意味します。ここで複数形を使用するのは、この脆弱性が複数回トリガーされ、hitme から 4G までのアドレスに 0 ~ 31 が書き込まれる可能性があるためです。

この脆弱性の悪用可能性は、VMware のバージョンとオペレーティング システムによって異なります。当然のことながら、スタック レイアウトはバージョンやオペレーティング システムによって異なります。

4. 安全でないメモリマッピングはDEPバイパスにつながる

vmware-vmx スーパーバイザー プロセスが起動すると、いくつかのメモリ マッピングが作成されます。驚いたことに、メモリ マッピングの 1 つが読み取り、書き込み、および実行権限で作成されました。これはプロセスのライフサイクル全体に当てはまります。このようなメモリ マップにはブロックが 1 つだけあります。ここで作成されるメモリ マッピングは、vmware-vmx プロセスのデータ セグメントの最初のページです。

  1. 7ff7`36b53000 7ff7`36b54000 0`00001000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READWRITE イメージ [vmware_vmx; 「C:\Program Files (x86)\VMware\VMware Workstation\x64\vmware-vmx.exe」 ]
  2.   
  3. 0:018>dq 7ff7`36b53000 L 0n1000/8
  4. 00007ff7`36b53000 ffffffff`ffffffff 00000001`fffffffe
  5. 00007ff7`36b53010 00009f56`1b68b8ce ffff60a9`e4974731
  6. 00007ff7`36b53020 00007ff7`36780a18 00007ff7`36780a08
  7. 00007ff7`36b53030 00007ff7`367809f8 00007ff7`367809e8
  8. 00007ff7`36b53040 00007ff7`367809d8 00000000`00000000
  9. 00007ff7`36b53050 00007ff7`36780990 00007ff7`36780940
  10. 00007ff7`36b53060 00007ff7`367808f0 00007ff7`367808a0
  11. 00007ff7`36b53070 00007ff7`36780860 00007ff7`36780820
  12. 00007ff7`36b53080 00007ff7`367807f0 00007ff7`367807a0
  13. 00007ff7`36b53090 00007ff7`36780750 00007ff7`36780700

明らかに、これによりシェルコードを実行するための完璧な領域が提供されるため、VM エスケープに対する脆弱性が大幅に軽減されます。

  1. データ:0000000140B33000 _データセグメントパラパブリック  「データ」使用64
  2. ...
  3. 0000000140B33000 FF FF FF FF FF FF FF FF FE FF FF FF 01 00 00 00 .....
  4. 0000000140B33010 32 A2 DF 2D 99 2B 00 00 CD 5D 20 D2 66 D4 FF FF 2..-.+...] .f...
  5. 0000000140B33020 18 0A 76 40 01 00 00 00 08 0A 76 40 01 00 00 00 [email protected]@....
  6. 0000000140B33030 F8 09 76 40 01 00 00 00 E8 09 76 40 01 00 00 00 [email protected]@....
  7. 0000000140B33040 D8 09 76 40 01 00 00 00 00 00 00 00 00 00 00 00 00 ..v@............
  8. 0000000140B33050 90 09 76 40 01 00 00 00 40 09 76 40 01 00 00 00 ..v@[email protected]@....
  9. 0000000140B33060 F0 08 76 40 01 00 00 00 A0 08 76 40 01 00 00 00 [email protected]@....
  10. 0000000140B33070 60 08 76 40 01 00 00 00 20 08 76 40 01 00 00 00 `.v@.... .v@....
  11. 0000000140B33080 F0 07 76 40 01 00 00 00 A0 07 76 40 01 00 00 00 [email protected]@....
  12. 0000000140B33090 50 07 76 40 01 00 00 00 00 07 76 40 01 00 00 00 [email protected]@....

図に示すように、メモリは読み取り、書き込み、実行の方法で割り当てられます。 Windbg のダンプは、IDA のデータ セクションと一致することを示すためだけのものです。

要約する

最初の 2 つの脆弱性はバージョン 12.5.3 のゼロデイ脆弱性であり、競合後もバージョン 12.5.4 ではこれらの脆弱性は修正されませんでした。

バージョン 12.5.4 のリリース直後、VMWare はこれら 2 つのヒープ関連の脆弱性を修正する VMSA-2017-0006 をリリースしました。バージョンアップデートの詳細は曖昧であり、これらの脆弱性が実際に修正されたかどうかはわかりません。

同様に、vmware-vmx のデバッグ バージョンには、製品バージョンにはないエラー チェック メカニズムがあります。 ZDI によれば、これは他者が報告した脆弱性と競合するものではなく、VMSA-2017-006 では ZDI の報告のみが言及されているとのことです。

そのため、これらの脆弱性に CVE ID があるかどうか、または他の研究者がそれらを発見したかどうかはわかりません。

ASSERT アサーションは他の SM4 命令にも影響することに注意してください。バージョン 12.5.5 までは、少なくとも dcl_indexRange と dcl_constantBuffer に同様のヒープ範囲外書き込みの脆弱性があると考えられます。

dcl_resource の脆弱性はバージョン 12.5.5 では修正されていません。

現時点では、最初のパッチは内部コードのリファクタリングであり、報告した脆弱性の修正ではないと考えています。デバッグ バージョンのパッチはリリース バージョンのパッチと同じであるためです。エラー処理関数の代わりにアサーションが使用されます。したがって、これらの脆弱性を利用して VMware に侵入することは依然として可能です。

この記事で説明した脆弱性の PoC は、https://github.com/comsecuris/vgpu_shader_pocs にあります。

他の

この記事の最後に、私たちの研究から得られたいくつかの発見についてお話ししたいと思います。皆さんのお役に立てれば幸いです。以下の点があります。

異なる環境でのリバースエンジニアリングの難しさ

vmware-vmx をリバースしたとき、Linux バージョンのいくつかの奇妙な組み込み関数機能により、リバース エンジニアリングがはるかに困難になりました (Windows や Mac と比較して)。比較した結果、Windows の vwmare-vmx が逆解析に最も適していることがわかりました。

Linux 版の vmware-vmx のシンボル情報は、リバース エンジニアリングに非常に役立ちます。

設定

VMware は、レンダラーと対話するための便利な設定を提供します。 mks.dx11.dumpShaders、mks.shim.dumpShaders、mks.gl.dumpShaders が役に立つことがわかりました。同様の設定はたくさんあります。

パイ

Linux では、vmware-vmx ELF ファイルから PIE オプションを削除すると、vmware-vmx は正常に動作しなくなります。 Mac では、change_macho_flage.py スクリプトは vmware-vmx の再配置を正常に処理できます。これによりデバッグがはるかに簡単になります。

バイナリ変換モジュール

上記の分析を完了した後も、x86 命令をシミュレートするためのコードが vmware-vmx のどこにあるかについてはまだ検討中です。当初は簡単に見つかるだろうと考えていましたが、今のところ関連するコードは見つかっていません。 1 つの可能性はハードウェア仮想化です。ただし、VMware はセットアップとアーキテクチャに応じて複数のモードで実行できます。このコードはどこかにあるはずです。

  1. binwalk vmware-vmx.exe
  2.   
  3. 10進数 16進数 説明
  4. --------------------------------------------------------------------------------------  
  5. 0 0x0 Microsoft 実行可能ファイル、ポータブル (PE)
  6. ...
  7. 13126548 0xC84B94 ELF、64ビットLSB 再配置可能、AMD x86-64、バージョン 1 (SYSV)
  8. 13126612 0xC84BD4 ELF、64ビットLSB 再配置可能、AMD x86-64、バージョン 1 (SYSV)
  9. 14073118 0xD6BD1E Unix パス: /build/mts/release/bora-4638234/bora/vmcore/lock/semaVMM.c
  10. 14256073 0xD987C9 Sega MegaDrive/Genesis 生のROMダンプ、名前: "tSBASE" "E_TABLE_VA"
  11. 14283364 0xD9F264 Sega MegaDrive/Genesis 生のROMダンプ、名前: "ncCRC32B64" "FromMPN"
  12. 14942628 0xE401A4 ELF、64ビットLSB 再配置可能、AMD x86-64、バージョン 1 (SYSV)
  13. 14949876 0xE41DF4 ELF、64ビットLSB 再配置可能、AMD x86-64、バージョン 1 (SYSV)
  14. 14954108 0xE42E7C ELF、64ビットLSB 再配置可能、AMD x86-64、バージョン 1 (SYSV)
  15. 14960892 0XE448FC ELF、64-ビットLSB Recatable、AMD X86-64、バージョン1(SYSV)
  16. 14991124 0XE4BF14 ELF、64-ビットLSB Recatable、AMD X86-64、バージョン1(SYSV)

ビンウォークがエルフを分析した結果は奇妙に見えます、何か間違ったものがあるに違いありません。とりあえずこれらのエラーを無視します。メモリにELFヘッダーがあることに気付きます。 Binwalkツール(通常、BinwalkはPEまたはELFファイルの分析に使用されていません)を使用して、いくつかの興味深いことを見つけました。

最大のELFファイルには、巨大な機能が含まれており、さらに重要なことにはシンボルがあるため、興味深いように見えます。

驚いたことに、この埋め込まれたエルフには、x86分解器用の翻訳ユニットが付属しています。私たちはそれがどのように機能するかに興味がありましたが、それが私たちの目標ではなかったので、私たちはそれを掘り下げませんでしたが、それは研究の興味深い方向です。

結論

残念ながら、PWN2Ownでは、完全な仮想マシンエスケープを達成するという当初の目標を達成することができませんでした。しかし、計画された時間内にそれを完了することができたことに非常に満足しています。 VMwareは、脆弱性の発見の興味深いターゲットであるだけでなく、VMwareが仮想マシン監視機能を実装しているが、従来のデスクトッププログラムとそれほど違いはないと考えています。

攻撃ポイントの発見と検出に基づいて、VMwareは、非常に複雑で広く使用されているソフトウェアとして、多くの未開拓の攻撃ポイントがあると考えています。たとえば、レンダラー翻訳ユニット構造の表面を傷つけただけです。

レンダラー機能の内部は複雑であり、まだ分析されていません。同様に、他のVMwareコンポーネントが攻撃されています。分析したコードと過去にVMwareが行ったセキュリティの推奨事項を読んだ後、最近のセキュリティ防御はパッシブからアクティブに変更されました。

コアコンポーネントに加えて、探索する価値のあるコンポーネントはたくさんあります。たとえば、vmware-hostd(SSLをサポートするWebサーバー)。仮想マシンのセキュリティ問題をさらに研究したいと考えています。他の人を同じことを歓迎します。

<<:  2018年のデジタルトランスフォーメーションのトレンドと分析: クラウドコンピューティングとIoTの深い統合

>>:  クラウドコンピューティングが成熟期に入る中、3つの主要業界のCIOが産業変革とイノベーションをどのように突破できるかを見てみましょう。

推薦する

Dockerイメージをバッチロードする最も簡単な方法

通常、Docker イメージ ファイルをバッチでロードする場合は、シェル ファイルを作成し、 for...

ウェブサイトのダウングレードに対処する方法についての簡単な説明

筆者はインターネット業界で4年間SEOに携わっており、その間に百度で大小さまざまな調整を経験してきま...

クラウド ストレージのセキュリティ: データ暗号化メカニズムとセキュリティ レベルの簡単な分析

「 2022年企業のマルチクラウド環境の保護」レポートの調査では、クラウド環境でデータにアクセス/維...

BaiduとGoogleの両方にウェブサイトを最適化する方法

今日はウェブサイト最適化の SEO テクニックについてお話しましょう。中国の検索は主に、Baidu ...

リベート ウェブサイトには良いものも悪いものもあり、その多くは中身のないものです。

ショッピングリベートが届くまで10日以上かかるオンラインショッピングは安く、リベートを利用すればさら...

プライベートクラウドプラットフォームは絶滅の危機から脱しつつある

企業は、パブリック クラウドを採用するか、プライベート クラウドを採用するかという選択に直面すること...

タオバオの売り手が過労で亡くなった場合、オンラインストアを健全に運営する方法

最近、若いタオバオの出店者が過労で亡くなり、毎日店舗の営業を停止したり倒産したりするタオバオの出店者...

推奨ウェブサイト: Clipix Pinterest と Evernote の組み合わせ

Pinterest のウォーターフォール フロー形式が成功した後、多くの Web サイトがその情報表...

5G時代のクラウドコンピューティングは企業の情報技術革新を支援

2019年10月31日、工業情報化部と3大通信事業者は5Gサービスの開始を正式に発表し、中国は正式に...

#Labor Day# 修正済み - 30% 割引コード/Shark データセンター/無制限トラフィック/年間支払いは 15 ドルから KVM VPS

rectified は「労働者の日」に新しい割引コードをリリースしました。すべての仮想ホスト、VPS...

クラウドネイティブ CI/CD フレームワーク Tekton の初体験

[[404558]] Tekton は、非常に強力で柔軟な CI/CD オープンソース クラウド ネ...

SEOにおける内部リンクの役割を分析する

Baidu の青大根アルゴリズムからザクロアルゴリズム、青大根アルゴリズム 2.0 まで、コンテンツ...

クラウド大手は AI 市場の残り 96% をどのように活用するのでしょうか?

私たちは、AIがあらゆる場所に存在する世界に向かっているようです。たとえば、基本的な食品配達のウェイ...

ftpit-$5/KVM/768m メモリ/2 コア/35g ハードディスク/2T トラフィック/incero Dallas

ftpit は、主に VPS 事業を行っている小規模な民間企業です。各 VPS には、Intel S...

ビットコイン取引プラットフォームGBLが暴走し、被害者は3000万ドル以上を失った

IT Times記者 ユー・シンフェイタイのビットコイン取引禁止や闇取引サイト「シルクロード」の崩壊...