Unsorted Bin Attack
基本情報
アンソートされたビンについての詳細は、このページを参照してください:
pageBins & Memory Allocationsアンソートリストは、チャンクのbk
アドレスにunsorted_chunks (av)
へのアドレスを書き込むことができます。したがって、攻撃者がアンソートビン内のチャンクのbk
ポインタのアドレスを変更できる場合、任意のアドレスにそのアドレスを書き込むことができ、これはlibcアドレスをリークしたり、いくつかの防御をバイパスするのに役立つ可能性があります。
したがって、基本的にこの攻撃は、任意のアドレスを大きな数値(ヒープアドレスまたはlibcアドレスである可能性があるアドレス)で上書きできるようにするものです。これにより、リークするスタックアドレスやグローバル変数**global_max_fast
**のような制限をバイパスして、より大きなサイズの高速ビンを作成できるようにすることができます(アンソートビン攻撃から高速ビン攻撃に移行します)。
https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principleで提供された例を見て、0x400と0x500の代わりに0x4000と0x5000を使用して(tcachesを避けるため)、現在はエラー**malloc(): unsorted double linked list corrupted
**がトリガーされることがわかります。
したがって、このアンソートビン攻撃は(他のチェックと共に)ダブルリンクリストを修正できる必要があるため、これがバイパスされるようにする必要があります。victim->bck->fd == victim
またはvictim->fd == av(arena)
ではないことを示します。つまり、書き込みたいアドレスのアドレスは、そのfd
位置に偽のチャンクのアドレスを持っている必要があり、偽のチャンクのfd
がアリーナを指している必要があります。
この攻撃はアンソートビンを破壊します(したがって、小さなビンと大きなビンも)。そのため、今後は高速ビンからの割り当てのみを使用できます(より複雑なプログラムは他の割り当てを行い、クラッシュする可能性があります)、これをトリガーするには同じサイズを割り当てる必要があります。
**global_max_fast
**を作成すると、この場合に役立つ場合があります。高速ビンがすべての他の割り当てを処理できることを信頼して、攻撃が完了するまでの間に。
guyinatuxedoのコードは非常によく説明していますが、mallocを変更して、tcacheに終わらないようにメモリを割り当てると、先に述べたエラーが発生し、このテクニックが防がれます:malloc(): unsorted double linked list corrupted
アンソートビン情報リーク攻撃
これは実際には非常に基本的な概念です。アンソートビン内のチャンクには、ビンを作成するためのダブルポインタがあります。アンソートビン内の最初のチャンクは、FDとBKリンクがメインアリーナ(libc)の一部を指すようになります。 したがって、アンソートビン内にチャンクを配置し、それを読み取る(使用後に解放)か、少なくとも1つのポインタを上書きせずに再度割り当てしてからそれを読み取ることができれば、libc情報リークを得ることができます。
このwriteupで使用された攻撃は、4つのチャンク構造(A、B、C、D - Dはトップチャンクとの統合を防ぐためだけ)を悪用し、Bのヌルバイトオーバーフローを使用してCにBが未使用であることを示すようにしました。また、Bではprev_size
データが変更され、サイズがBのサイズではなくA+Bになりました。
その後、Cが解放され、A+Bと統合されました(ただし、Bはまだ使用中)。サイズAの新しいチャンクが割り当てられ、その後、リークしたlibcアドレスがBに書き込まれ、そこからリークされました。
参照およびその他の例
グローバル変数を4869より大きい値で上書きしてフラグを取得し、PIEが有効になっていない場合にフラグを取得できるようにすることが目標です。
任意のサイズのチャンクを生成し、望ましいサイズのヒープオーバーフローがあります。
攻撃は、3つのチャンクを作成して開始します:オーバーフローを悪用するためのchunk0、オーバーフローされるchunk1、前のチャンクが統合されないようにするためのchunk2。
次に、chunk1が解放され、chunk0がオーバーフローされ、chunk1の
bk
ポインタがbk = magic - 0x10
を指すようにします。次に、chunk3がchunk1と同じサイズで割り当てられ、アンソートビン攻撃がトリガーされ、グローバル変数の値が変更され、フラグを取得できるようになります。
マージ関数は脆弱です。渡された両方のインデックスが同じ場合、それに対してreallocし、それを解放して、その解放された領域へのポインタを返すことができます。
したがって、2つのチャンクが作成されます:chunk0は自分自身とマージされ、トップチャンクとマージされるのを防ぐためのchunk1。その後、マージ関数がchunk0を2回呼び出され、使用後に解放されることになります。
次に、**
view
**関数が使用され、インデックス2(使用後に解放されたチャンクのインデックス)が呼び出され、libcアドレスがリークします。バイナリは**
global_max_fast
より大きいサイズのmallocのみを許可する保護を持っているため、fastbinは使用されず、アンソートビン攻撃が使用されてグローバル変数global_max_fast
を上書き**することができます。その後、インデックス2(使用後に解放されたポインタ)を使用してedit関数を呼び出し、
bk
ポインタをp64(global_max_fast-0x10)
を指すように上書きします。その後、以前に侵害された解放アドレス(0x20)を使用して新しいチャンクを作成すると、アンソートビン攻撃がトリガーされ、global_max_fast
が非常に大きな値で上書きされ、今後は高速ビンでチャンクを作成できるようになります。今度は高速ビン攻撃が実行されます:
まず、**
__free_hook
の場所でサイズ200の高速チャンクを操作できることがわかります:
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
もし、この場所にサイズ0x200の高速チャンクを取得できれば、実行される関数ポインタを上書きすることが可能になります
そのために、サイズが
0xfc
の新しいチャンクが作成され、そのポインタでマージされた関数が2回呼び出され、これによりサイズ0xfc*2 = 0x1f8
の解放されたチャンクへのポインタが高速ビンに得られます。次に、このチャンクで編集関数が呼び出され、この高速ビンの**
fd
アドレスを以前の__free_hook
**関数を指すように変更します。その後、サイズが
0x1f8
のチャンクが作成され、高速ビンから以前の無効なチャンクを取得し、**__free_hook
に高速ビンチャンクを取得するために別のサイズが0x1f8
のチャンクが作成され、system
**関数のアドレスで上書きされます。最後に、文字列
/bin/sh\x00
を含むチャンクが解放され、削除関数が呼び出され、**__free_hook
**関数がトリガーされ、/bin/sh\x00
をパラメータとして持つsystemにポイントされます。アンソートビンでチャンクを統合し、libc情報リークを取得し、その後mallocフックをワンガジェットアドレスで上書きするための高速ビン攻撃を実行するための1Bオーバーフローを悪用する別の例
Last updated