Recently, in many of my CTF adventures, I have encountered a lot of heap exploitation related problems. I initially had a lot of trouble with them, but then decided to study it a lot and hope to explain it to other readers too. In this first blog post (I will be making a series of these), I will discuss the UAF, Double Free, and the Fastbin Attacks.
Before starting, please understand the structure of dynamic memory in Linux and how malloc and free works (glibc). Here is an excellent resource on it from sploitsfun.Now let's get started. I'm assuming you all understand bins, chunks, and memory allocation in Linux now after reading sploitsfun guide.
Let's start discussing these three exploits.
1. Use after Free.
Apparently, some silly programmers still use variables after freeing them (and they don't even set it to NULL after freeing!). If such variables point to a location on the heap, this leads to a use after free. If the programmer uses malloc (which does not zero out memory), exploitation becomes easy due to glibc malloc's first fit behavior. For non-fastbin sized chunks, freed memory goes into the binlist from the head first and the lookup for them starts from the tail. For fastbin sized chunks, freed memory goes in from the head and leaves from the head. Once we request memory again, we can still retrieve previously freed memory (the size needs to work out correctly or be nearly similar though) and they would still retain previous contents in them due to malloc's inability to zero them out (and if the data is somehow seen as a pointer, you can start doing really nasty things, especially if the program has conditions based on previously "freed" items). You can see use after free in this writeup of mine about a CTF problem.
PicoCTF sword.
2. Double Free.
This is a silly bug too that is also worsened by malloc's first fit behavior. One security check Linux binaries do is that you cannot free the two same things in the row. However, if you free something in between the two same things, you can bypass this security check (not for smallbins though). Once you request memory again, you can basically write/control data that is still seen as a freed chunk. Assuming you know the structure of free chunks, you now can start forging chunks, as you will see in the next section.
3. Fastbin attack.
Due to double free, we can control chunks that are still stored in the heap because of pointers. Since the forward pointers in fastbin chunks are in the user data section when allocated, we can write fake forward pointers in fastbin chunks now. With this ability, we can achieve arbitrary write very easily, which can change program flow. One common example is overwriting __malloc_hook, which is built into libc as a mechanism to change program flow. By simply manipulating the allocated data section to contain a pointer to the runtime address of __malloc_hook, that region of memory becomes a forged chunk and you will be able to access it once it becomes the head of the fastbin singly linked list. And now, you can write to it once you receive it and perhaps change malloc to system! One problem though... there is a security check to make sure the forward pointer points to something that is in the same (and valid) fastbin chunk range. This limits many possibilities, but if you find data nearby that can be interpreted as the same chunk, you can use that data instead (misalignment). Afterwards, you will need to find the correct offset to write to your target data. You can see fastbin attacks in action in this writeup of mine about a CTF problem.
PicoCTF contacts.
In the next few parts of this series, I will discuss heap unlinking, shrinking attacks, and the famous House of ______ heap attacks.