Lecture 8 Heap Exploitation
Introduction to Heap
- Heap is extremely dependent on the implementation, OS, specific implementation details
- Is a modern exploitation technique
- Need to understand the structure of the heap and how it works
- Heap exploitation is basically mixing data and control
- Harder to identify
- called malloc in certian order, or called free twice etc.
- Attacking the implentation of the heap, not programmers
What is the Heap?
- OS provides memory (through
mallocAPI) in multiples of 0x1000 - Different libraries, OS etc. use different heap management implementations
- Heap exploitation is hard
- You can’t just ‘guess and check’.
- need to understand the program to solve any heap challenge
Malloc Implentations
There are several different malloc implementations
dlmalloc: general purpose, no threads, very oldptmalloc2(glibc): fast for single-threaded applications, and fast for very small allocations. Also supports multithreading- Chrome and Firefox have their own malloc implentations (tcmalloc, jemalloc) for more specialised
- There is a
malloc_hookfunction (ptr) that allows you to specify your own memory allocator
- There is a
How does Malloc Work?
- Dynamic memory allocator
- Allocates a large chunk of memory (through a syscall), and then
- returns
struct malloc_chunk
- returns
- ‘First Fit’ allocator (usually)
- What’s to return the first chunk that will fulfill the request
- Each chunk stores metadata on either side of it (see
struct malloc_chunkcontents)
- Maintains a ‘free’ list so it can quickly jump through free blocks
- Some fields of the struct are only used if the chunk is free
sizeincludes the metadatafdis what is returned to the malloc user (and the following addresses are inbk). But if the block is free, it is a pointer to the next chunk.- On the first allocation, a large chunk is allocated. The first n bytes are the requested bytes from malloc, and the remaining region is the top chunk. We then break off the top of the top chunk each time we need more.
- Global variable in libc called
main_arenadescribes the heap
How does Free work?
- Free needs to be fast. (Fast Code = low security)
- The free chunks are divided into different sizes
- and within the size classes, the chunks are sorted into bins (bucket sort)
- So essentially an O(1) to return a chunk of a certain size
- Bins are arrays of linked lists of chunks
- The nodes in the linked lists are old chunks
- Fast Bins are multiples of 8.
- Array of linked lists of chunks of certian sizes
- Always take first off the list - so O(1) retrieval
- Never merge bins
- Small Bins
- Faster than large bins
- Each bin maintains a doubly linked list (FIFO)
- Each bin has chunks of same size.
- There are more small bins
- When you free two chunks adjacent to each other: then the chunks are coalesced into one larger chunk
- Unsorted Bin
- Initially a free chunk is put into an unsorted bin
- When a new chunk is allocated, it loops through this list and sorts the chunks until the correct size is found.
- tcache
- Very simliar to fast bins, except they removed all the security checks
- The only check it does is to ensure that there aren’t already max chunks in the tcache.
Exploits
It’s hard to exploit a program with only one of these vulnerabilities. You usually need a few to perform exploitation.
- Use after free
- You can overwrite the forward pointer, and corrupt the free list struture
- Can also provide leaks
- Double free
- In fastbins, it will check that the free request is not the first item in the free list already (tcache doesn’t). To get double free, need to have something in between the frees so that the check passes
- Leaking with small chunks
- The small bins point back into the main arena (in libc).
- (The first element’s backward pointer points into libc)
- If you can print the first thing in smallbin list, you have an address leak into libc!
- The small bins point back into the main arena (in libc).
- Forging chunks
- Corrupt the free structure to forge a chunk wherever you like in memory
- Heap Spray
Usually the goal is to get two chunks to overlap and overwrite data in another chunk.
ROP is hard on with heap (because you can’t control the stack), so one_gadget is the saviour.
pwndbg Commands
| Command | Purpose |
|---|---|
heap |
Shows all chunks allocated, and their types |
bins |
Shows type of bins |
vis_heap_chunks |
Visualise the heap chunks |
Need to make sure using the same libc library
LD_PRELOADallows you to force a program to use a different libc version- Need to do this in case the algorithms are different in different versions.