githubEdit

House of Roman

circle-check

Basic Information

This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben patchedarrow-up-right.

Code

Goal

  • RCE by abusing relative pointers

Requirements

  • Edit fastbin and unsorted bin pointers

  • 12 bits of randomness must be brute forced (0.02% chance) of working

Attack Steps

Part 1: Fastbin Chunk points to __malloc_hook

Create several chunks:

  • fastbin_victim (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value.

  • chunk2 (0x80, offset 0x70): For good alignment

  • main_arena_use (0x80, offset 0x100)

  • relative_offset_heap (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk

Then free(main_arena_use) which will place this chunk in the unsorted list and will get a pointer to main_arena + 0x68 in both the fd and bk pointers.

Now it's allocated a new chunk fake_libc_chunk(0x60) because it'll contain the pointers to main_arena + 0x68 in fd and bk.

Then relative_offset_heap and fastbin_victim are freed.

  • fastbin_victim has a fd pointing to relative_offset_heap

  • relative_offset_heap is an offset of distance from fake_libc_chunk, which contains a pointer to main_arena + 0x68

  • Just changing the last byte of fastbin_victim.fd it's possible to make fastbin_victim points to main_arena + 0x68

For the previous actions, the attacker needs to be capable of modifying the fd pointer of fastbin_victim.

Then, main_arena + 0x68 is not that interesting, so lets modify it so the pointer points to __malloc_hook.

Note that __memalign_hook usually starts with 0x7f and zeros before it, then it's possible to fake it as a value in the 0x70 fast bin. Because the last 4 bits of the address are random there are 2^4=16 possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: 0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23).

(For more info about the rest of the bytes check the explanation in the how2heaparrow-up-right examplearrow-up-right). If the BF don't work the program just crashes (so start gain until it works).

Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the __malloc_hook:

Part 2: Unsorted_bin attack

For more info you can check:

Unsorted Bin Attackchevron-right

But basically it allows to write main_arena + 0x68 to any location by specified in chunk->bk. And for the attack we choose __malloc_hook. Then, after overwriting it we will use a relative overwrite) to point to a one_gadget.

For this we start getting a chunk and putting it into the unsorted bin:

Use an UAF in this chunk to point unsorted_bin_ptr->bk to the address of __malloc_hook (we brute forced this previously).

triangle-exclamation

So, to trigger the write of main_arena + 0x68 in __malloc_hook we perform after setting __malloc_hook in unsorted_bin_ptr->bk we just need to do: malloc(0x80)

Step 3: Set __malloc_hook to system

In the step one we ended controlling a chunk containing __malloc_hook (in the variable malloc_hook_chunk) and in the second step we managed to write main_arena + 0x68 in here.

Now, we abuse a partial overwrite in malloc_hook_chunk to use the libc address we wrote there(main_arena + 0x68) to point a one_gadget address.

Here is where it's needed to bruteforce 12 bits of randomness (more info in the how2heaparrow-up-right examplearrow-up-right).

Finally, one the correct address is overwritten, call malloc and trigger the one_gadget.

References

circle-check

Last updated