Libc Protections
Reading time: 14 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
チャンクアライメントの強制
Mallocは8バイト(32ビット)または16バイト(64ビット)のグループでメモリを割り当てます。これは、32ビットシステムではチャンクの終わりが0x8に整列し、64ビットシステムでは0x0に整列する必要があることを意味します。このセキュリティ機能は、ポインタをビンから使用する前に、各チャンクがこれらの特定の位置で正しく整列しているかをチェックします。
セキュリティの利点
64ビットシステムにおけるチャンクアライメントの強制は、偽のチャンクの配置を16アドレスごとに1つに制限することによって、Mallocのセキュリティを大幅に向上させます。これにより、特にユーザーが入力値を制限された状況での攻撃が複雑になり、成功させるのが難しくなります。
- __malloc_hookに対するファストビン攻撃
Mallocの新しいアライメントルールは、__malloc_hook
に関する古典的な攻撃も阻止します。以前は、攻撃者はチャンクサイズを操作して**この関数ポインタを上書きし、コード実行を得ることができました。現在、厳格なアライメント要件により、そのような操作はもはや実行可能ではなく、一般的な悪用経路が閉じられ、全体的なセキュリティが向上します。
ファストビンとtcacheにおけるポインタのマングリング
ポインタのマングリングは、メモリ管理操作においてファストビンおよびtcache Fdポインタを保護するために使用されるセキュリティ強化です。この技術は、特に漏洩したメモリ情報を必要としない、または既知の位置に対してメモリ位置を直接操作するタイプのメモリ悪用戦術を防ぐのに役立ちます(相対的な上書き)。
この技術の核心は、難読化の公式です:
New_Ptr = (L >> 12) XOR P
- Lはポインタのストレージ位置です。
- Pは実際のファストビン/tcache Fdポインタです。
ストレージ位置(L)を12ビット右にシフトしてからXOR操作を行う理由は重要です。この操作は、メモリアドレスの最下位12ビットの決定論的な性質に内在する脆弱性に対処します。これらのビットは、システムアーキテクチャの制約により通常予測可能です。ビットをシフトすることで、予測可能な部分が方程式から外れ、新しいマングルされたポインタのランダム性が向上し、これらのビットの予測可能性に依存する悪用から保護されます。
このマングルされたポインタは、プログラムが使用するアドレスをランダム化する**アドレス空間配置のランダム化(ASLR)**によって提供される既存のランダム性を活用します。
ポインタを元のアドレスに戻すデマングリングは、同じXOR操作を使用して行います。ここでは、マングルされたポインタが公式のPとして扱われ、変更されていないストレージ位置(L)とXORされると、元のポインタが明らかになります。このマングリングとデマングリングの対称性により、システムは大きなオーバーヘッドなしにポインタを効率的にエンコードおよびデコードでき、メモリポインタを操作する攻撃に対するセキュリティが大幅に向上します。
セキュリティの利点
ポインタのマングリングは、ヒープ管理における部分的および完全なポインタの上書きを防ぐことを目的としており、セキュリティの大幅な向上です。この機能は、悪用技術にいくつかの方法で影響を与えます:
- バイト相対的上書きの防止: 以前は、攻撃者はポインタの一部を変更してヒープチャンクを異なる位置にリダイレクトすることができましたが、ポインタのマングリングにより、そのような相対的上書きはヒープの漏洩なしではブルートフォースを必要とし、成功の可能性が大幅に減少します。
- tcacheビン/ファストビン攻撃の難易度の増加: 関数ポインタ(
__malloc_hook
など)を上書きする一般的な攻撃は、ファストビンまたはtcacheエントリを操作することによって妨げられます。たとえば、攻撃はLibCアドレスを漏洩させ、チャンクをtcacheビンに解放し、Fdポインタを上書きして__malloc_hook
にリダイレクトし、任意のコード実行を行うことが含まれるかもしれません。ポインタのマングリングにより、これらのポインタは正しくマングルされる必要があり、正確な操作にはヒープの漏洩が必要であり、悪用の障壁が高まります。 - 非ヒープ位置でのヒープの漏洩の必要性: スタック、.bssセクション、またはPLT/GOTのような非ヒープ領域に偽のチャンクを作成することは、ポインタのマングリングの必要性からヒープの漏洩を必要とします。これは、LibCアドレスを操作するための要件と同様に、これらの領域を悪用する複雑さを拡張します。
- ヒープアドレスの漏洩がより困難になる: ポインタのマングリングは、ファストビンおよびtcacheビンにおけるFdポインタの有用性を制限し、ヒープアドレスの漏洩源としての役割を果たします。ただし、未ソート、小、大のビンのポインタはマングルされていないため、アドレスの漏洩に使用可能です。この変化により、攻撃者は悪用可能な情報を探すためにこれらのビンを探索する必要がありますが、一部の技術では、制約があるものの、漏洩前にポインタをデマングルすることが可能です。
ヒープの漏洩を伴うポインタのデマングリング
caution
プロセスのより良い説明については、こちらの元の投稿を確認してください。
アルゴリズムの概要
ポインタのマングリングとデマングリングに使用される公式は次のとおりです:
New_Ptr = (L >> 12) XOR P
ここで、Lはストレージ位置、PはFdポインタです。Lが12ビット右にシフトされると、Pの最上位ビットが露出します。これは、XORの性質により、ビットが自分自身とXORされると0を出力するためです。
アルゴリズムの主要なステップ:
- 最上位ビットの初期漏洩: シフトされたLをPとXORすることにより、Pの上位12ビットを効果的に取得します。シフトされた部分のLはゼロになるため、Pの対応するビットは変更されません。
- ポインタビットの回復: XORは可逆的であるため、結果とオペランドの1つを知っていれば、他のオペランドを計算できます。この特性を利用して、マングルされたポインタの部分と既知のビットセットを順次XORすることで、Pのビット全体を推測します。
- 反復デマングリング: このプロセスは繰り返され、各回で前のステップから得られたPの新たに発見されたビットを使用して、マングルされたポインタの次のセグメントをデコードします。すべてのビットが回復されるまで続けます。
- 決定論的ビットの処理: Lの最終的な12ビットはシフトによって失われますが、これらは決定論的であり、プロセス後に再構築できます。
このアルゴリズムの実装はここにあります: https://github.com/mdulin2/mangle
ポインターガード
ポインターガードは、glibcで使用される悪用緩和技術で、特にatexit()
のようなライブラリ呼び出しによって登録された関数ポインタを保護します。この保護は、ポインタをスクリューム(難読化)することによって行われ、64ビットの秘密とXORを行い、ビット単位の回転を適用します。このメカニズムは、攻撃者が関数ポインタを上書きすることによって制御フローをハイジャックするのを防ぐことを目的としています。
漏洩を伴うポインターガードのバイパス
- ポインターガード操作の理解: ポインタのスクリューム(マングリング)は、ポインタを64ビットの秘密とXORし、0x11ビットの左回転を行う
PTR_MANGLE
マクロを使用して行われます。元のポインタを回復するための逆操作はPTR_DEMANGLE
によって処理されます。 - 攻撃戦略: 攻撃は、攻撃者がポインタの元のバージョンとマングルされたバージョンの両方を知る必要がある既知の平文アプローチに基づいています。
- 既知の平文を悪用する:
- 固定関数ポインタの特定: glibcのソースコードや初期化された関数ポインタテーブル(
__libc_pthread_functions
など)を調べることで、攻撃者は予測可能な関数ポインタを見つけることができます。 - 秘密の計算:
__pthread_attr_destroy
のような既知の関数ポインタと、その関数ポインタテーブルからのマングルされたバージョンを使用して、マングルされたポインタを右回転させてから関数のアドレスとXORすることで秘密を計算できます。
- 代替平文: 攻撃者は、0や-1のような既知の値でポインタをマングルして、これらがメモリ内で識別可能なパターンを生成するかどうかを確認することもできます。これにより、メモリダンプ内でこれらのパターンが見つかった場合に秘密が明らかになる可能性があります。
- 実用的な応用: 秘密を計算した後、攻撃者は制御された方法でポインタを操作し、libcベースアドレスの知識と任意のメモリ位置を読み取る能力を持って、マルチスレッドアプリケーションにおけるポインターガード保護を実質的にバイパスできます。
参考文献
- https://maxwelldulin.com/BlogPost?post=5445977088
- https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。