In a previous article, I’ve discussed an old (but important) category of memory-corruption vulnerability called “stack buffer overflows”, and how we, as attackers, can exploit these vulnerabilities to take control of a remote program and make it run our shellcode.

For applications that make use of an exploit mitigation called “stack canaries”, it turns out that these stack-buffer-overflow vulnerabilities can be harder for attackers to exploit and often require additional vulnerabilities to exploit them reliably. When developers are using various stack-based exploit mitigations, attackers often instead build their exploits using heap-related vulnerabilities such as use-after-frees, double-frees, and heap-overflows. These heap-based vulnerabilities are more difficult to understand than their stack-based counterparts because attack techniques against heap-based vulnerabilities can be very dependent on how the internal implementation of the heap allocator actually works.

For this reason, before I write about exploiting heap-based vulnerabilities, I will use the first two parts of this series to talk about how the heap works. This first post will be an introduction into some high-level concepts, and a discussion about how new heap chunks are created. In the next post I will do a deeper dive into the technical implementation of how chunks are freed and recycled.

The way the heap works is very platform and implementation specific; lots of different heap implementations exist. For example, Google Chrome’s PartitionAlloc is very different to the jemalloc heap allocator used in FreeBSD. The default glibc heap implementation in Linux is also very different to how the heap works in Windows. So for this and the next few posts, I’ll be focusing on the glibc heap allocator, i.e. how heap allocations work for C/C++ programs running on Linux devices by default. This heap is derived from the ptmalloc heap implementation, which is itself derived from the much older dlmalloc (Doug Lea malloc) memory allocator.