Windows 8-SMEPにしましょう!



Ivy Bridgeアーキテクチャに基づく新世代のIntelプロセッサの登場により、新しいセキュリティハードウェアが導入されました。 Intel SMEPと呼ばれます。 メモリページでのコードの実行を妨げるNXビットと同様に、カーネルモードの脆弱性の悪用に頭痛の種を追加します。



次に、MicrosoftはWindows 8でSMEPサポートを実装したため、このOSはさらに安全になりました。 しかし、SMEPサポートの最初の実装「正面」は小さな欠陥であることが判明したため、攻撃者は依然として彼にとって比較的痛みのない脆弱性を悪用する可能性があります。



SMEPとは何ですか?



SMEPは「Supervisor Mode Execution Prevention」の略で、スーパーバイザーモードでのコード実行を防ぎます。 スーパーバイザーモードは、Windows 8のカーネルが実行される優先プロセッサモードであり、OSの観点から、このモードはカーネルモードとも呼ばれます。 反対はユーザーモードです。このモードでは、ユーザーアプリケーションが実行されます。



OS保護は、ユーザーアプリケーションが特権操作、たとえばI / Oポート、プロセッサ制御レジスタなどへのアクセスを実行できないという事実に基づいています。 さらに、カーネルモードで使用されるメモリは、ユーザーモードアクセスから保護されます。 ユーザーアプリケーションは、カーネルメモリでコードを直接読み取り、変更、または実行することはできません。 OSカーネルとの相互作用は、システムコールインターフェイスを介して間接的に発生します。



特権モードには、SMEP用でない場合、制限がありません。 オンの場合、ユーザーアプリケーションのメモリにあるコードを実行しようとすると、ページフォールトが発生します。 特に、Windows 8のページエラーハンドラーでは、この状況によりバグチェックが発生します。

簡単に言えば、カーネルのドライバーまたはシステムモジュールがユーザーアプリケーションのメモリにあるコードを実行しようとすると、悲しい顔文字で死のブルースクリーンですべて終了します。



ポイントは何ですか?



カーネルモードの脆弱性は、攻撃者にとって最も「おいしい」ものです。攻撃が成功すると、攻撃者はターゲットシステムを完全に制御できるからです。 要点は、カーネルモードで脆弱性を悪用する場合、攻撃者は原則として、シェルコードを格納するためにユーザーモードでメモリを割り当てることです。



「しかし、カーネルモードでは、ユーザーメモリのページからコードを実行できなくなりました! そして、シェルコードをどこに保存するのですか? 独自のシェルコードなしの攻撃のポイントは何ですか? それとも、攻撃する必要はないのでしょうか?」



このような攻撃者の一連の思考を期待して、このテクノロジーが作成されました。 実装を念頭に置いて、他の防御メカニズムで「後」をカバーする場合、エンドユーザーをあらゆる種類の攻撃から保護することができます。







最初のパンケーキはゴツゴツしている



考え直してみましょう。 ユーザー空間にシェルコードを保存することはできません。 つまり、カーネルメモリに配置する必要があり(選択肢は大きくありません-2つのモードのみ)、このメモリセクションの内容は私たちが制御する必要があり(ユーザーモードから直接書き込むことはできません)、ユーザーモードからこのメモリセクションのアドレスを見つけることができるはずです(できません)ユーザーモードから直接読み取ります)。 シェルコードをカーネルに配信するために何を使用できますか?



最も明らかな解決策は、Windowsオブジェクトを使用することです。 アプリケーションが記述子(ハンドル)を介して動作するもの。 これらはすべての種類のタイマー、イベント、ミューテックス、I / O完了ポート、グラフィックオブジェクトなどです。 そのようなオブジェクトの本体はカーネルメモリにあり、その内容はユーザーモードから変更できます。また、カーネルスペースのどのアドレスにあるかを調べることができます!



たとえば、CreateFile()関数でファイルを開くと、開いているファイルへのハンドルを取得します。 アプリケーションがこのファイルの数バイトをバッファーに読み込む必要がある場合、ReadFile()関数を呼び出します。これは、システムコールを使用して、OSカーネルに制御を転送し、そこで記述子テーブルから目的のファイルオブジェクトを見つけます。 この場合、オブジェクトのタイプは_FILE_OBJECTで、その変数フィールドはファイル名です。 つまり 理論的には、シェルコードを含む「\ 0xBAADC0DE」というファイルを作成できます。 次に、特定のカーネルモードの脆弱性を悪用し、制御をシェルコードに転送します。



0:kd> dt nt!_FILE_OBJECT

+ 0x000タイプ:Int2B

+ 0x002サイズ:Int2B

...

+ 0x050フラグ:Uint4B

+ 0x058ファイル名:_UNICODE_STRING

+ 0x068 CurrentByteOffset:_LARGE_INTEGER

...

+ 0x0c0 IrpList:_LIST_ENTRY

+ 0x0d0 FileObjectExtension:Ptr64 Void



成功? まだまだです。 実際、Windows 8上のSMEPは別のセキュリティメカニズムによって補完されます。 コードがカーネルモードページにあるという事実にもかかわらず、このページには実行可能ではないというマーク(ビットNX)があります。 このページではコードを実行できません! Windowsオブジェクトは実行から保護されているため、シェルコードを保存するのにも適していません。 このステートメントは、x64バージョンのWindows 8に当てはまります。ただし、x86バージョンのグラフィックオブジェクトの本体は、実行可能メモリにあります。



パレットは、シェルコードを配信するのに最適なオブジェクトであることが判明しました。 CreatePalette()関数とLOGPALETTE構造を使用して作成され、その内容にはシェルコードが含まれています。 それでも、パレットの色を検証する方法は? 実際、私たちのパレットでは、まさに私たちが望む色になります! そして、多くのバイトのNOP(0x90)と多くのバイトのシェルコードが必要になります。 これが「邪悪な」パレットです...







Windows 8 x86でのSMEPバイパススキームの合計:

1.「邪悪な」LOGPALETTE構造を作成し、シェルコードで埋めます。

2. CreatePalette()を使用してパレットを作成します。

3.共有GDIテーブルを使用して、カーネル内のパレットオブジェクトのアドレスを見つけます。

4.パレットオブジェクトから特定のオフセットで制御を移します。

5. ???????

6.利益!!!



そして、x64で何をしますか?



Windows 8 x64でSMEPの回避策が必要ですか? 私はそれらを持っています! おそらくこの方法はそれほど面白くないかもしれませんが、機能しています。 x64上のSMEPは、Return Oriented Programming(ROP)を使用してバイパスされます。 要するに、ROPは既にメモリに存在する他のモジュールのコードのセクションを使用します。 したがって、シェルコードをカーネルに転送する必要はありません。



もちろん、この場合のペイロードの準備における攻撃者の能力は非常に限られています。 ただし、攻撃者が必要とするのはSMEPを無効にすることだけです。このため、ntoskrnlモジュールにはHvlEndSystemInterrupt()およびKiConfigureDynamicProcessor()関数の形式で「提示」があります。 これらの関数の最後のバイトを使用すると、特定のプロセッサでSMEPを無効にできます。



HvlEndSystemInterrupt(): … pop rax pop rcx retn
      
      







 KiConfigureDynamicProcessor(): … mov cr4, rax add rsp, 28h retn
      
      







 // ROP chain to refresh cr4 value // vTrash vROPChain DWORD_PTR dwRopStack[7 + 10] = {0}; // HvlEndSystemInterrupt gadget dwRopStack[7 + 0] = dwKernelBase + HvlGadgetOffset; // New CR4 value dwRopStack[7 + 1] = 0x00000000000506F8; // KiConfigureDynamicProcessor dwRopStack[7 + 3] = dwKernelBase + Cr4GadgetOffset; // Out address (shellcode) dwRopStack[7 + 9] = (DWORD_PTR)pTestBuf;
      
      











制限付きでダウン



SMEPを無効にすると、攻撃者はユーザーバッファーからコードを実行できます。 シェルコードのサイズにはこれ以上の制限はありません。 SMEPを無効にするために使用されたカーネルの脆弱性を使用して、既に「悪」シェルコードに転送することができます。



おわりに



もちろん、両方の方法は普遍的ではありません。 各脆弱性には、独自の悪用機能があります。 場合によっては、回避策を完了する必要がありますが、通常は回避策は適用されません。



また、これ自体が悪用可能な脆弱性ではないことを理解することも重要です。 これは、保護メカニズムの1つを回避する方法であり、他の悪用可能な脆弱性と組み合わせてのみ使用できます。



PS SMEPは13バイトのコードによって無効にされます。 詳細については、以下のリンクに従ってください。

Windows 8 x86でSMEPを破る方法

Windows 8 x64でSMEPに勝つ方法



著者:Artyom ShishkinおよびIlya Smith



All Articles