Note: the addresses got moved cuz I restarted the binary
Freeing the first one...
wdb> heap chunks
address prev_size size inuse fd bk
0x7a8000 0x290 used
0x7a8290 0x20 free 0x7a8
0x7a82b0 0x20 free 0x7a8508
0x7a82d0 0x20 free 0x7a8568
0x7a82f0 0x20 free 0x7a8548
0x7a8310 0x20 free 0x7a84a8
0x7a8330 0x20 free 0x7a8488
0x7a8350 0x20 free 0x7a84e8
0x7a8370 0x20 used
0x7a8390 0x20 free 0x7a8 (a)
0x7a83b0 0x20 used(b)
0x7a83d0 0x20 used(c)wdb> heap fast
(0x20) fastbin[0]:0x7a8390(a gets freed so it gets put on the fastbin free list)(0x30) fastbin[1]: 0x0
(0x40) fastbin[2]: 0x0
(0x50) fastbin[3]: 0x0
(0x60) fastbin[4]: 0x0
(0x70) fastbin[5]: 0x0
(0x80) fastbin[6]: 0x0
If we free a (0x7a83a0) again, things will crash because a (0x7a83a0) is at the top of
the free list.
So, instead, we'll free b (0x7a83c0).
wdb> heap chunks
address prev_size size inuse fd bk
⋮ ⋮ ⋮
0x7a8370 0x20 used
0x7a8390 0x20 free 0x7a8
0x7a83b0 0x20 free 0x7a8438
0x7a83d0 0x20 usedwdb> heap fast
(0x20) fastbin[0]: 0x7a83b0 -> 0x7a8390(a -> b)
⋮ ⋮
(0x80) fastbin[6]: 0x0
Now, we can free a (0x7a83a0) again, since it's not the head of the free list.
wdb> heap fast
(0x20) fastbin[0]:0x7a8390 -> 0x7a83b0 -> 0x7a8390 (duplicate entry)(a -> b -> a)
Now the free list has [ 0x7a83a0, 0x7a83c0, 0x7a83a0 ]. If we malloc 3 times, we'll get 0x7a83a0 twice!
(malloc uses the last element on the free list [a, b, a], hence we get a (0x7a83a0) twice)(0x20) fastbin[0]:0x7a8390 -> 0x7a83b0 -> 0x7a8390 (duplicate entry)(a -> b -> a)
1st calloc(1, 8): 0x7a83a0 (there is an offset of 0x10 for the header metadata)(0x20) fastbin[0]: 0x7a8390 -> 0x7a83b0 -> (invalid memory)
2nd calloc(1, 8): 0x7a83c0
(0x20) fastbin[0]:0x7a8390 -> (invalid memory)
3rd calloc(1, 8): 0x7a83a0
(0x20) fastbin[0]:(invalid memory)
The danger here is that 2 different mallocs will be pointing to the same chunk
This can be exploited if 1 chunk that gets malloc()ed has sensitive information, and the user can access it by doing some operation on the program that runs another malloc() and leak that input
fastbin_dup_consolidate
1 2
void* p1 = malloc(0x40); void* p2 = malloc(0x40);
Allocated two fastbins: p1=0xc0f010 p2=0xc0f060
wdb> heap chunks
address prev_size size inuse fd bk
0xc0f000 0x50 used
0xc0f050 0x50 used