# First Fit {{#include ../../../banners/hacktricks-training.md}} ## **First Fit** プログラムでglibcを使用してメモリを解放すると、異なる「ビン」がメモリチャンクを管理するために使用されます。ここでは、一般的な2つのシナリオ:未整理ビンとファストビンの簡略化された説明を示します。 ### 未整理ビン ファストチャンクでないメモリチャンクを解放すると、それは未整理ビンに入ります。このビンは、新しく解放されたチャンクが前方(「ヘッド」)に追加されるリストのように機能します。新しいメモリチャンクを要求すると、アロケータは未整理ビンの後方(「テイル」)から見て、十分な大きさのチャンクを探します。未整理ビンのチャンクが必要なサイズより大きい場合、それは分割され、前の部分が返され、残りの部分はビンに残ります。 例: - 300バイト(`a`)を割り当て、その後250バイト(`b`)を割り当て、`a`を解放し、再度250バイト(`c`)を要求します。 - `a`を解放すると、それは未整理ビンに入ります。 - その後、再度250バイトを要求すると、アロケータはテイルで`a`を見つけて分割し、リクエストに合う部分を返し、残りをビンに保持します。 - `c`は以前の`a`を指し、`a`の内容で埋められます。 ```c char *a = malloc(300); char *b = malloc(250); free(a); char *c = malloc(250); ``` ### Fastbins Fastbinsは小さなメモリチャンクに使用されます。未整理ビンとは異なり、fastbinsは新しいチャンクを先頭に追加し、後入れ先出し(LIFO)動作を作成します。小さなメモリチャンクを要求すると、アロケータはfastbinの先頭から取得します。 例: - 20バイトのチャンクを4つ(`a`、`b`、`c`、`d`)割り当てます。 - それらを任意の順序で解放すると、解放されたチャンクはfastbinの先頭に追加されます。 - その後、20バイトのチャンクを要求すると、アロケータはfastbinの先頭から最も最近解放されたチャンクを返します。 ```c char *a = malloc(20); char *b = malloc(20); char *c = malloc(20); char *d = malloc(20); free(a); free(b); free(c); free(d); a = malloc(20); // d b = malloc(20); // c c = malloc(20); // b d = malloc(20); // a ``` ## その他の参考文献と例 - [**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を上書きする**。ユーザーを再利用して**パスワードチェックをバイパスする**。 - [**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(\)へのポインタがあります。 - 攻撃は、ノート情報サイズよりも大きなmalloc内容を持つ2つのノート(note0とnote1)を作成し、それらを解放してファストビン(またはtcache)に入れることです。 - 次に、内容サイズ8の別のノート(note2)を作成します。内容はnote1にあり、チャンクが再利用されるため、関数ポインタをwin関数を指すように変更し、その後note1をUse-After-Freeして新しい関数ポインタを呼び出します。 - [**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が含まれます。