-
Notifications
You must be signed in to change notification settings - Fork 1
Heap
This is the best resource out there for learning about heap: https://heap-exploitation.dhavalkapil.com/.
Nice bin diagrams at https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/.
uaf.io
has some of the best CTF chal heap tutorials http://uaf.io/exploitation/2017/03/19/0ctf-Quals-2017-BabyHeap2017.html
malloc_chunk
diagrams at http://etutorials.org/Networking/network+security+assessment/Chapter+13.+Application-Level+Risks/13.5+Heap+Overflows/
malloc_state
diagram: http://uaf.io/assets/malloc_state.png
- Know where all the mallocs and frees are! Do I control sizes passed to malloc? Are there size restrictions? How do I trigger mallocs and frees?
Use angelboy's angelheap for heap commands
heapinfo
, parseheap
, tracemalloc on
, etc.
I also use voltron memory view to get a live view of the heap region.
voltron view memory --address <heapaddr> -w 2
Leak a libc address and a heap address (two birds with one stone!) by printing contents of a free unsorted bin chunk (flink and blink pointers). Assumes you have overlapping chunks somehow.
-
malloc_hook
First, find themain_arena
address; thenmalloc_hook
is&main_arena-0x16
The next time malloc
is called, the overwritten hook will be run. Note that malloc hooks are disabled starting from glibc 2.34.
-
top_chunk
Change the location that malloc serves chunks from.
If you have fastbins, try to use fastbin attack to overwrite a fd
ptr of a chunk.
Fastbin attacks -> Allow you to allocate a malloc chunk ANYWHERE.
Allocate a chunk over the stack? Overwrite return address, bypass canary.
Allocate a chunk over libc? Overwrite malloc_hook
or top_chunk
.
Only restriction is that the size
of fastbin chunk must be a valid fastbin size. This is ok because fastbin sizes are everywhere in memory, 0x7f
for libc/stack addresses and 0x55
for code/heap addresses.
If you have smallbins/unsorted bins, try to get overlapping chunks -> leak + write heap data.
What can you overwrite size
and prev_size
fields with? Just a null byte is enough, see House of Einherjar.
You can also forge a fake chunks on the heap 'out of thin air', by writing fake size
and prev_size
as user data. You can use these to satisfy security checks or trigger consolidations, etc.
Allocate a sequence of chunks at beginning of exploit so you have space to work with.
Allocate a small chunk at the end, to prevent accidental consolidations with top chunk.
When you encounter one, look it up to see why it triggered and when. Then, go back and fix the constraint. You can try testing on a malloc playground instead of the challenge binary to figure out how to bypass the check.
In GDB:
If you have debug symbols in your libc, you can get the address with symbol &main_arena
.
x/40gx (long long)(&main_arena)-0x30
pwndbg
has the arena(s)
utility to show the location of main_arena.
Another way without symbols, suggested by uafio, is to find the address of the top chunk in the heap, then search memory for references to it.
> search -8 0x555555757060
libc-2.24.so 0x7ffff7dd3b58 0x555555757060 /* '`puUUU' */
and subtract 0x58
to get the main_arena
address.