Translated ['src/binary-exploitation/libc-heap/use-after-free/first-fit.

This commit is contained in:
Translator 2025-08-20 09:38:03 +00:00
parent c3059dd538
commit 09db65a9ef

View File

@ -15,7 +15,7 @@ glibcを使用してプログラム内のメモリを解放すると、異なる
- 300バイト`a`を割り当て、その後250バイト`b`)を割り当て、`a`を解放して再度250バイト`c`)を要求します。
- `a`を解放すると、それは未ソートビンに入ります。
- その後再度250バイトを要求すると、アロケータはテイルにある`a`を見つけて分割し、リクエストに合う部分を返し、残りをビンに保持します。
- `c`は以前の`a`を指し、`a`の内容で満たされます。
- `c`は以前の`a`を指し、`a`の内容で埋められます。
```c
char *a = malloc(300);
char *b = malloc(250);
@ -42,9 +42,9 @@ c = malloc(20); // b
d = malloc(20); // a
```
---
### 🔥 現代のglibcに関する考慮事項 (tcache ≥ 2.26)
### 🔥 現代のglibc考慮事項 (tcache ≥ 2.26)
glibc 2.26以降、各スレッドは自分自身の**tcache**を保持し、これは未整理ビンの*前に*照会されます。したがって、ファーストフィットのシナリオは**次の条件を満たす場合にのみ**到達されます:
glibc 2.26以降、各スレッドは自分自身の**tcache**を保持し、これは未ソートビンの*前に*照会されます。したがって、ファーストフィットのシナリオは**次の条件を満たす場合にのみ**到達されます:
1. リクエストされたサイズが**`tcache_max`より大きい**デフォルトで64ビットの0x420、*または*
2. 対応するtcacheビンが**すでに満杯または手動で空にされている**7つの要素を割り当てて使用中に保持することによって
@ -55,12 +55,12 @@ glibc 2.26以降、各スレッドは自分自身の**tcache**を保持し、こ
for(int i = 0; i < 7; i++) pool[i] = malloc(0x100);
for(int i = 0; i < 7; i++) free(pool[i]);
```
tcacheが枯渇すると、その後のfreeは未整列ビンに移動し、従来のファーストフィットの動作(テイルサーチ、ヘッド挿入)が再びトリガーされる可能性があります。
tcacheが枯渇すると、その後の解放は未整列ビンに移動し、古典的なファーストフィットの動作(テイルサーチ、ヘッド挿入)が再びトリガーされる可能性があります。
---
### 🚩 ファーストフィットを使用したオーバーラップチャンクUAFの作成
以下のフラグメントglibc 2.38でテスト済みは、未整列ビンのスプリッタを悪用して2つの**オーバーラッピングポインタ**を作成する方法を示しています。これは、単一のfreeをwrite-after-freeに変換する強力なプリミティブです。
以下のフラグメントglibc 2.38でテスト済みは、未整列ビンのスプリッタを悪用して2つの**オーバーラッピングポインタ**を作成する方法を示しています。これは、単一の解放を解放後書き込みに変換する強力なプリミティブです。
```c
#include <stdio.h>
#include <stdlib.h>
@ -93,37 +93,35 @@ fwrite(C2, 1, 0x10, stdout); // prints Xs
Exploitation recipe (common in recent CTFs):
1. **ターゲットサイズのtcacheを排出**します。
2. **チャンクを解放**して、未ソートビンに配置します。
3. **わずかに小さいサイズを割り当て**ます アロケータが未ソートチャンクを分割します。
2. **チャンクを解放**して、未ソートビンに配置します。
3. **わずかに小さいサイズを割り当て**ます アロケータが未ソートチャンクを分割します。
4. **再度割り当て**ます 残りの部分が既存の使用中のチャンクと重なります → UAF。
5. 敏感なフィールド関数ポインタ、FILE vtableなどを上書きします。
実用的なアプリケーションは、2024 HITCON Quals *Setjmp* チャレンジに見られ、この正確なプリミティブがUAFから`__free_hook`の完全制御にピボットするために使用されます。{{#ref}}
../../../../references/2024_setjmp_firstfit.md
{{#endref}}
実用的なアプリケーションは、2024 HITCON Quals *Setjmp* チャレンジに見られ、この正確なプリミティブがUAFから`__free_hook`の完全制御にピボットするために使用されます。
---
### 🛡️ 緩和策と強化
* **セーフリンクglibc ≥ 2.32**は、単一リンクの*tcache*/**fastbin**リストのみを保護します。未ソート/小/大ビンは依然として生のポインタを格納しているため、ヒープリークを取得できればファーストフィットに基づく重なりが有効です。
* **ヒープポインタの暗号化とMTE**ARM64は、まだx86-64 glibcには影響しませんが、`GLIBC_TUNABLES=glibc.malloc.check=3`のようなディストリビューションの強化フラグは、一貫性のないメタデータで中止し、単純なPoCを壊す可能性があります。
* **解放時のtcacheの充填**2024年にglibc 2.41のために提案)は、未ソートの使用をさらに減少させるでしょう。一般的なエクスプロイトを開発する際は、今後のリリースを監視してください。
* **Safe-linking (glibc ≥ 2.32)** は、単一リンクの*tcache*/**fastbin**リストのみを保護します。未ソート/小/大ビンは依然として生のポインタを格納しているため、ヒープリークを取得できればファーストフィットに基づく重なりが有効です。
* **ヒープポインタの暗号化とMTE** (ARM64) は、まだx86-64 glibcには影響しませんが、`GLIBC_TUNABLES=glibc.malloc.check=3`のようなディストリビューションの強化フラグは、一貫性のないメタデータで中止し、単純なPoCを壊す可能性があります。
* **解放時のtcacheの充填** (2024年にglibc 2.41に提案) は、未ソートの使用をさらに減少させます。一般的なエクスプロイトを開発する際は、今後のリリースを監視してください。
---
## その他の参考文献と例
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- ARM64. Use after free: ユーザーオブジェクトを生成し、それを解放し、解放されたチャンクを取得するオブジェクトを生成し、それに書き込むことを許可します。**前のものからuser->passwordの位置を上書きします**。ユーザーを再利用して**パスワードチェックをバイパスします**
- ARM64. Use after free: ユーザーオブジェクトを生成し、それを解放し、解放されたチャンクを取得して書き込むオブジェクトを生成し、**以前のユーザーのuser->passwordの位置を上書き**します。ユーザーを再利用して**パスワードチェックをバイパス**します。
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- プログラムはートを作成することを許可します。ートには、malloc(8)内のート情報呼び出すことができる関数へのポインタを含むと、ートの内容を持つ別のmalloc(<size>)へのポインタがあります。
- 攻撃は、ート情報サイズよりも大きなmalloc内容を持つ2つのートnote0とnote1を作成し、それらを解放してファーストビンまたはtcacheに入れることです。
- 次に、内容サイズ8の別のートnote2を作成します。内容はnote1にあり、チャンクが再利用されるため、関数ポインタをwin関数を指すように変更し、その後Use-After-Freeを使用してnote1を呼び出します。
- 次に、内容サイズ8の別のートnote2を作成します。内容はnote1にあり、チャンクが再利用されるため、関数ポインタをwin関数を指すように変更し、その後Use-After-Freeを使用してnote1を呼び出します。
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- メモリを割り当て、希望の値を書き込み、それを解放し、再割り当てすることが可能です。前のデータがまだそこにあるため、新しい期待される構造に従って扱われ、値を設定してフラグを取得することが可能になります。
- メモリを割り当て、希望の値を書き込み、解放し、再割り当てすることが可能で、以前のデータがまだ存在するため、チャンク内の新しい期待される構造に従って扱われ、値を設定してフラグを取得することが可能になります。
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- この場合、特定のチャンク内に4を書き込む必要があります。これは、すべてを強制的に解放した後でも最初に割り当てられたものです。新しく割り当てられた各チャンクの配列インデックス内の番号が保存されます。次に、4つのチャンク最初に割り当てられたものを含むを割り当て、最後のものには4が含まれ、解放して最初のものの再割り当てを強制します。これにより、最後に解放されたチャンクが使用され、その中に4が含まれます。
- この場合、特定のチャンク内に4を書き込む必要があります。これは、すべてを強制的に解放した後でも最初に割り当てられたものです。新しく割り当てられた各チャンクの配列インデックス内の番号が保存されます。次に、4つのチャンク最初に割り当てられたものを含むを割り当て、最後のものに4を入れ、解放して最初のものの再割り当てを強制します。これにより、最後に解放されたチャンクが使用され、その中に4が入っています。
- 2024 HITCON Quals Setjmpの書き込みQuarkslab 実用的なファーストフィット/未ソートスプリット重なり攻撃: <https://ctftime.org/writeup/39355>
- Angstrom CTF 2024 *heapify*の書き込み 未ソートビンの分割を悪用してlibcをリークし、重なりを得る: <https://hackmd.io/@aneii11/H1S2snV40>
- Angstrom CTF 2024 *heapify* の書き込み 未ソートビンの分割を悪用してlibcをリークし、重なりを得る: <https://hackmd.io/@aneii11/H1S2snV40>
{{#include ../../../banners/hacktricks-training.md}}