インテルは、マイクロプロセッサーが関与するエクスプロイトに対する保護の新しい概念の予備仕様を
公開しました 。 Control-flow Enforcement Technology(CET)と呼ばれる新しい技術に専念する彼の
投稿では、彼は何らかの目的で
ROPメソッドを使用するエクスプロイトに対する保護のモデルについて説明しています。 通常、ROPはシステムのDEPをバイパスするために使用されます。 この保護対策(DEP)もマイクロプロセッサを使用して実装され、仮想メモリデータのRWページを非実行可能(NX)としてマークします。

CETはシャドウスタックの概念を導入します。シャドウスタックは、マイクロプロセッサ自体によって管理され、
retステートメントで後で使用するためにリターンアドレスに関する情報を格納します。 スレッドが関数から戻ると、マイクロプロセッサはスレッドスタックに格納されているリターンアドレスとシャドウスタックに格納されているリターンアドレスをチェックし、一致しない場合はOSによって処理される例外をスローします。 CETは、このプロセスを自動化し、ROPを使用するエクスプロイトに効果的に対処するOSのインターフェイスを定義します。
シャドウスタックの下に個別の仮想メモリ領域が割り当てられ、ページテーブルのPTE要素のレベルでそのようにマークされます。 したがって、マイクロプロセッサは、このスタックにアクセスするための1つまたは別のコードの試みをブロックします(たとえば、
mov命令を介して)。 マイクロプロセッサは、タスク状態セグメントの既知の構造にシャドウスタックへのポインタを格納し、スレッドとそのプロセスのコンテキストを切り替えるときにこのフィールドを追跡します。 この構造のフィールドは、プロセスサービスメカニズムとコンテキストスイッチングのためにWindowsによって部分的に使用されます。
CETは、コントロール転送とデータに使用される従来のスタックに加えて、コントロール転送操作専用に使用される2番目のスタック(シャドウスタック)を定義します。 CETが有効になっている場合、CALL命令は、リターンアドレスを通常のスタックにプッシュする通常の動作に加えて、リターンアドレスをシャドウスタックにプッシュします(従来のスタック操作に変更はありません)。 リターン命令(RETなど)は、シャドウスタックと従来のスタックの両方からリターンアドレスをポップし、両方のスタックからのリターンアドレスが一致する場合にのみ、ポップされたアドレスに制御を転送します。
CR4.CETと呼ばれるcr4レジスタの特別なフラグは、マイクロプロセッサレベルでCETをアクティブにします。 彼のために、CETの動作を制御する特別なMSRレジスタのセット全体が割り当てられます:IA32_U_CET、IA32_S_CET、IA32_PL3_SSP、IA32_PL2_SSP、IA32_PL1_SSP、IA32_PL0_SSP、IA32_INTERRUPT_SSP_TABLE_ADDR。 シャドウストリームスタックの現在のアドレスは、SSP(シャドウスタックポインター)と呼ばれる新しいマイクロプロセッサレジスタによって修正されます。

図 意図されていないページにストリームにアクセスしようとしたときにマイクロプロセッサによって生成される既知のページフォールト例外のエラーコード形式。 例外の結果として設定される6番目のビットは、シャドウスタックで仮想メモリページへのストリームへのアクセスの試みを示します。
シャドウスタックは、使用規則がOSによって規制されているマイクロプロセッサ命令を使用して制御できます。 それらのいくつかを以下に示します。
- INCSSP-SSPシャドウスタックポインターを1ステップ、つまり32ビットシステムでは4バイト、64ビットシステムでは8バイト増やします。
- RDSSP-SSPポインターの値を指定されたレジスターに読み取ります。
- SAVESSP-現在の「シャドウスタックマーカーコンテキスト」をシャドウスタックに保存し、SSPポインターを8バイトに揃えます。
- RSTORSSP-コマンドは前のコマンドと似ています。つまり、保存されたスタックマーカーの値をSSPに書き込みます。
- WRSS-仮想メモリのSSPポインターを使用して、渡された引数の値を書き込みます。
その活動の場合、CETは、コード実行フローを変更する次のマイクロプロセッサ命令に応答します:CALL、INT n / INTO / INT3、JMP、RET、SYSCALL、SYSENTER、SYSEXIT、SYSRET、IRET / IRETD。 ご覧のとおり、これらの手順は、関数の呼び出しと終了のメカニズム、およびシステムサービスの呼び出しと終了、割り込みの呼び出しと終了に関するものです。

図 呼び出し関数
呼び出し命令の疑似コードの一部。 CETアクティビティの場合、戻りアドレスはシャドウスタックに格納されることがわかります。

図
ret関数のexit関数の擬似コードの一部。 ストリームスタックとシャドウスタックのアドレスが一致しない場合、例外がスローされることがわかります。

図 シャドウスタックページが59番目のSSSビットでマークされている拡張ページテーブル(EPT)ページ要素。 ページテーブルレベルでシャドウスタックのページを識別するために使用されます。
ROPエクスプロイトとの戦いの特定の機能が無料のEMETツールに含まれていることを思い出してください。 このために、Caller Check、SimExecFlow、MemProt、StackPivotなどの設定が使用されます。 最初の2つにより、EMETは実行のフローを制御し、Windows APIの関数を呼び出し、呼び出し元のコードの正当性を検証できます。 MemProt関数は、スレッドがスタックページのセキュリティ属性を変更するのを防ぎ、StackPivotは、スタックピボットメソッドを使用して、espレジスタの変更状況を認識します。