ROPベースのバッファオーバーフロー攻撃を防ぐために使用される開発者のカウンターコントロールフロー整合性(CFI)をどのように悪用しますか?
元々、リターン指向プログラミング(ROP)は、スタックの非実行(NX)保護に対抗するために、異なるメモリ位置(実行可能)からジャンプしてコード(ガジェット)を実行することによって発明されました。
ただし、制御フロー整合性(CFI)は、ジャンプの宛先の有効性を動的にチェックすることにより、ROPベースの実行を防止することを目的としています。 。)
エクスプロイト開発者は、バッファオーバーフローを使用してNXで保護されたプログラムをエクスプロイトするためにCFIにどのように対抗しますか?
CFIには多くのタイプがあります。ただし、前方エッジ保護と後方エッジ保護の両方をサポートし、確定的であり、きめ細かいCFIが実現することは非常にまれです(私が知っている唯一の具体例は、PaX RAPの商用バージョンです)。ほとんどのCFIは粗粒度です。つまり、関数はその1つの関数だけでなく、同じ関数シグネチャ(つまり、同じ戻り値の型とまったく同じ)の多数の関数に戻ることができます。引数)。フォワードエッジはジャンプとコールに由来し、バックワードエッジはリターンに由来します。 CFIの大部分はどちらか一方(MicrosoftのCFGやClangのCFIなど)のみをサポートし、その機能を大幅に制限します。
CFIのもう1つの問題は、秘密の値を使用して確率的になることが多いことです。その秘密の価値を露呈するあらゆる情報漏えいは、CFIを破るために使用される可能性があります。確定的CFIはこれに悩まされませんが、ほとんどの確定的CFIは非常に粗いです。要約すれば:
ほとんどのCFIはフォワードエッジとバックワードエッジの両方ではなく、その機能を大幅に制限しています。
ほとんどのCFIは確率的であり、それを破壊する可能性のある情報漏洩に対して脆弱です。
ほとんどのCFIは粒度が粗く、同じシグネチャを持つ関数のgroupsに戻ることができます。
KCFIとPaX RAPをチェックすることで、実際のCFI実装についてさらに多くを学ぶことができます。私が知っている唯一の2つは、完全な前方および後方Edge保護を提供します。残念ながら、CFIは非常に複雑なトピックであり、one実装もCFIの手法もないため、攻撃者が実装を指定せずにそれを回避する方法を正確に回答する方法はありません。