Fast Bin Attack

Here are a list of key properties of FastBins

  • Single Linked List - LIFO

  • 10 bins, sizes of 8 bytes to 80 bytes

  • Two Adjacent Freed FastBins will not consolidate

  • FD and BK pointers point to the next and previous chunk respectively

So what happens if we perform a double free on a FastBin chunk? Let's look at this example by how2heap

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main()
{
	setbuf(stdout, NULL);

	printf("This file demonstrates a simple double-free attack with fastbins.\n");

	printf("Fill up tcache first.\n");
	void *ptrs[8];
	for (int i=0; i<8; i++) {
		ptrs[i] = malloc(8);
	}
	for (int i=0; i<7; i++) {
		free(ptrs[i]);
	}

	printf("Allocating 3 buffers.\n");
	int *a = calloc(1, 8);
	int *b = calloc(1, 8);
	int *c = calloc(1, 8);

	printf("1st calloc(1, 8): %p\n", a);
	printf("2nd calloc(1, 8): %p\n", b);
	printf("3rd calloc(1, 8): %p\n", c);

	printf("Freeing the first one...\n");
	free(a);

	printf("If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
	// free(a);

	printf("So, instead, we'll free %p.\n", b);
	free(b);

	printf("Now, we can free %p again, since it's not the head of the free list.\n", a);
	free(a);

	printf("Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);
	a = calloc(1, 8);
	b = calloc(1, 8);
	c = calloc(1, 8);
	printf("1st calloc(1, 8): %p\n", a);
	printf("2nd calloc(1, 8): %p\n", b);
	printf("3rd calloc(1, 8): %p\n", c);

	assert(a == c);
}
  1. First we allocate 3 FastBin Chunks

  2. We then follow up with a double free with a alternate chunk in the middle so as to not trigger malloc(): memory corruption (fast)

  3. Our fastbin free list is now circular and if we allocate three times more with the same size, malloc returns the same fastbin address twice!

We can leverage this to allow malloc to return a arbitrary pointer address to the stack or heap by utilizing UAF to change the fd pointer of the duped fastbin chunk to an address that we want.

Something to take note of here is to ensure that the fake chunk that fd is pointing to must have a valid chunk size.

This can be combined with heap consolidation via unsorted bin to get a libc leak.

We can see that the last two malloc calls return the same pointer to p1 which has been consolidated with the large chunk allocated. If we have a UAF on p1, we can potentially get a libc leak via main_arena+88.

Last updated