The toddler’s introduction to Heap Exploitation, FastBin Dup Consolidate (Part 4.2)

In this post we are going to trigger a FastBin consolidation which we are going to combine with a double free vulnerability (dup) in order to return a pointer to an already allocated chunk. By consolidation we refer to the process of merging adjacent free chunks and placing them to the unsorted bin for future allocations.

As always, please find below the references to my previous posts relative to heap exploitation:

Back to our topic, a consolidation is performed by the malloc_consolidate which is a specialised version of the free() function[1]:

This function will iterate the FastBin list merging a free chunk to its next and/or previous ones (4766–4783) and the result chunk will be added to the unsorted bin list (4784). A consolidation can be triggered by the malloc function, when special conditions occur:

It is also triggered by the malloc_init_state, malloc_trim, __libc_mallopt as well as the free function if the size of the freed chunk is ≥ 64KB:

https://sourceware.org/

We’ll stick to the malloc for this post as it is the most straightforward way to trigger the Fastbins consolidation.

FastBin Dup Consolidate

We are going to use the following program:

Although the code above is pretty much self-explanatory, let’s take some time to highlight few points:

  • At Lines 11–14 we fill the tcache list in order to force the FastBin usage.
  • At Lines 16–20 freeing p1 will add the corresponding chunk to the FastBin list since the tcache list is already full for this size (0x40).
  • The next allocation (Line 22) will trigger the consolidation of the chunks in the FastBin list. The p3 pointer though will point to the same address as p1 due to the fact that the p1 chunk has been merged.
  • Freeing p1 (again at Line 22) will add the chunk to the tcache even though it is still referenced by the p3.
  • At Line 33 we request a size which can be satisfied by the tcache’s last addition (0x400). So p4 will now point to the same address as p3.

Let’s load the program in gdb to see everything in action:

Set a breakpoint after the free(p1) and after hitting it check the heap bins:

Now step into the malloc up to the _int_malloc function, where we notice a call to the checked_request2size:

On a subsequent branch, _int_malloc will check if the requirement can be satisfied by the fastbins (using the get_max_fast()):

As the we requested a size of 0x400 bytes, this check will fail thus we will end up to the malloc_consolidate invocation:

Right after this call the chunk at 0x5555555598e0 has been merged:

Now malloc will return the 0x5555555598e0 as the new chunk address reference to satisfy the allocation (see last before the top chunk below):

The double free of p1 will move the chunk to the tcache:

Finally, the last call to malloc will assign the already allocated chunk to p4 (see $rax below) and this completes our proof of concept:

[1] https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;hb=45a8e05785a617683bbaf83f756cada7a4a425b9

[2] https://sourceware.org/glibc/wiki/MallocInternals#Thread_Local_Cache_.28tcache.29

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
+Ch0pin🕷️

+Ch0pin🕷️

https://www.linkedin.com/in/valsamaras/, developer of https://github.com/Ch0pin/medusa. Posts are solely my own and do not express the views of my employer.