いうていけろ

hideo54のブログ

トップページ
技術

SECCONサイバー甲子園2016に行って優勝してきた & writeup

2016年11月13日

この記事は最終更新から半年以上経過しており、内容が古い可能性があります。

SECCONCTF体験記writeup中高生向け

本日 SECCON2016 京都大会 「サイバー甲子園」というものがあり、行って優勝してきました。

登録

Twitter で nkpoid がリンクを貼っていたのを見て、一緒に出ることにする。 チーム名を “elf” に決め、リーダーを (ランダムで) 僕に決定した。

申請の時に英語、数学、理科、社会、保険体育の学校での成績や得意分野、特技、将来の夢を入力させられたのが謎だった (フラグ)。

抽選通過から本番まで

抽選の結果参加できることになったらしい。追加で国語の成績を聞かれたり、交通費申請をしたりした。京都での実施だったため、大阪在住である僕にとってはありがたみが薄かった (ケチ)。

CTF はセキュリティ・キャンプで初めてやって以来だった (当時は普通に何もできなかった) ので、 SECCON は CTF ではないという話を各所で耳にしつつも 対策しなきゃいけないなあと焦ってはいたが、結局忙しくて何もできなかった。

ただ唯一対策と言えそうなこととして、ググって出てきた去年の writeup を2つくらい流し読みしておいた。後述するが、去年と同じような問題が1問あったので、結果として少しだけ役に立った。

当日

前日は学校の遠足で嵐山に行っていたため、2日連続の京都ということで微妙な気持ちになっていた。(家から遠くもないけど近くもないので微妙に疲労感が溜まる)

東京からやってきた nkpoid と京都駅で会ってやっと当日気分になってきた。一緒にラーメンを食べて会場に向かった。

案内されたルートを無視して小路を通り逆側から向かった結果校門を間違え、到着が数分遅れてしまった (申し訳ありませんでした)。あと、印鑑を持ってきたものの朱肉を忘れてしまった (ISUCONでの反省が活きていない)。

適当にアナウンスを聞き競技開始。

競技(writeup)

やっと writeup です。自分が関わった問題のみ。残りは nkpoid が書いてくれるはずや。

[Sample 10] TRY FIRST

問題に書かれているフラグを投げるだけ。

[Crypto 100] very easy

よく覚えてない。very easy。

[Crypto 200] decode the flag

flag.encrypted というファイルと 53CC0NZOl6 というパスワードを渡され、openssl コマンドで暗号化したものですと言われる。

というわけで以下のようなシェルスクリプトを書いて総当り。

array=(aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb aes-256-cbc aes-256-ecb base64 bf bf-cbc bf-cfb bf-ecb bf-ofb cast cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb des des-cbc des-cfb des-ecb des-ede des-ede-cbc des-ede-cfb des-ede-ofb des-ede3 des-ede3-cbcdes-ede3-cfbdes-ede3-ofb des-ofb des3 desx rc2 rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb rc2-ecb rc2-ofb rc4 rc4-40 seed seed-cbc seed-cfb seed-ecb seed-ofb)
for i in "${array[@]}"
do
    echo $i
    openssl $i -d -in flag.encrypted -k 53CC0NZOl6
    echo -e "\n---\n"
done

結果から正常に FLAG として出てきたものを回答。

[Network 200] sample

pcap が渡されるので Wireshark で開く。最初見た時、単に ping しあってるだけに見えてさっぱりわからなかった。nkpoid に見てもらい、「TTL が毎度異なっているのが怪しそう。ASCII かと思ったけど違う。ずらすのかな。後は任せる」的なことを言われたので再度引き受ける。

確かに、レスポンスを返す側は常に一定の TTL で返しているのに対し、リクエストを送る側は61, 61, 61, 80, 66, 64,...と変わっていっている。 というわけで、この数字をずらして ASCII コードを出してみる Python プログラムを書く。(例 2ずらし: 63, 63, 63, 82, 68, 66,...)

ttls = [61, 61, 61, 80, 66, 64, 64, 76, 75, 120, 77, 102, 107, 100, 70, 112, 75, 108, 68, 108, 108, 97, 122]

for i in range(0, 10):
    str = ''
    for j in ttls:
        str += chr(j+i)
    print str

すると4文字ずらしくらいで flag が出てきた。

今見て気づいたのですが、逆方向へのずらしが考慮できていない。(例 -1ずらし: 60, 60, 60, 79, 65, 63, ...) まあ、運が良かったですね。

[Programming 100] x2.txt

「2倍した」みたいな感じのヒントワードとともに x2.txt というファイルが渡される。これは罠で、テキストファイルではない。 とりあえず vim->:%!xxd でバイナリ表示してみる。

9240 d0c2 ecca 40c2 40e0 cadc 5c40 9240
d0c2 ecca 40c2 dc40 c2e0 e0d8 ca5c 40a6
8a86 869e 9cf6 d8e6 d0d2 cce8 bede e4be
e4e6 d0d2 cce8 fa42 0a

nkpoid に「2倍したって言われてこれ見せられてどう思います?」って聞いて「半分にしてみては」と言われる。それはそう。

各バイトを10進にして半分にし、それらを Hex に戻してつなげ、ASCII コードで出してみる Python プログラムを書く。

s = '9240 d0c2 ecca 40c2 40e0 cadc 5c40 9240 d0c2 ecca 40c2 dc40 c2e0 e0d8 ca5c 40a6 8a86 869e 9cf6 d8e6 d0d2 cce8 bede e4be e4e6 d0d2 cce8 fa42 0a00'

result = ''

array = s.split(' ')
for i in array:
    first = int(i[0]+i[1], 16)
    hex1 = hex(first/2).lstrip('0x')
    if len(hex1) == 1:
        hex1 = '0' + hex1
    result += hex(first/2).lstrip('0x')
    # --
    second = int(i[2]+i[3], 16)
    hex2 = hex(second/2).lstrip('0x')
    if len(hex2) == 1:
        hex2 = '0' + hex2
    result += hex(second/2).lstrip('0x')

print result
print result.decode('hex')

Python の hexコマンドは 0xAB みたいな感じに 0x をつけてくるので、lstrip でそれを削除。また、12 → 0xC のように、15以下だと1文字で返ってくるので、その場合は先端に0を足す。 そんな感じで結合した Hex を ASCII コードとして10進に変えると flag が出てくる。めでたしめでたし。

[Programming 200] decode the trapezoid QR code

ねじれた QR コードの画像を渡される。Illustrator で逆方向にねじって QR コードを読んだらフラグがあった。Programming とは。 (ちゃんとプログラミングで解いている人もいて感心した)

[Programming 100] sum primes

12345番目から3万なんとか番目 (忘れた) の素数の和を出せという問題。

エラトステネスのふるいを使って Python プログラムを書いてみたものの正解できず、nkpoid に頼んでも、nkpoid も不正解。その後、運営から「解答が間違っていたので修正します」との報告が入る (オイオイ…)。

そして数十分後 (オイオイ…)、修正されたと言われ、nkpoid が提出して正解。

[Trivia 100] acronym

どんなんやったっけな。忘れた。簡単だったことだけ覚えている。

[Trivia 100] blacked out PDF

一部が黒塗りになっている PDF が与えられた。「オッこれ過去問で見たぞ」と思った (まんまそのままだった)。

文字の上から黒塗りにされているだけなので、辺り一帯のテキストをコピーすれば、黒塗りの下の文字もコピーされる。それだけ。

[Trivia 200] blacked out PDF again

同じような PDF の、パスワードがかかっている版。表示は見られるが、テキストをコピーしようとするとパスワードを求められる。

どうせ下にはテキストがあるんだからどうにかして見られるのだろうなと思ったけど、わからなかったので、パスワード総当りしてみることにした。

qpdf というツールがあるらしいので、 brew install qpdf でインストール。

以下のような総当りシェルスクリプトを書いた。

alphabet=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
for i in "${alphabet[@]}"
do
    qpdf --decrypt --password=$i owabi2.protected.pdf after.pdf && exit;
done

もし qpdf の decrypt が成功すれば、パスワードを外した版である after.pdf が生成され終了、失敗すればエラーが出るという仕組み。

実行してみる。 …エラーしか出ない。パスワードは1字ではないということか。

alphabet=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
for i in "${alphabet[@]}"
do
    for j in "${alphabet[@]}"
    do
        qpdf --decrypt --password=$i$j owabi2.protected.pdf after.pdf && exit;
    done
done

実行してみる。無事パスワードなし PDF が生成された。前述の通りテキストをコピーして FLAG を抽出。

今見返してみると大文字アルファベットや数字や記号入りのパスワードを考慮していない…。 偶然パスワードが小文字アルファベット2字だったから良かったですね。運が良かった。

競技まとめ

使ったソフトやツール

特筆すべきものはこんな感じかな?

  • Wireshark: pcapを読む
  • qpdf (brew): コマンドラインからパスワードつきPDFを開く
  • Illustrator: 画像の変形 (GIMPでいいと思います)
  • strings コマンド: わからんかったらとりあえずこれ叩いた

プログラミングが必要となった時は、総当りなどでコマンドを叩くのがメインのものはシェルスクリプト、そうでなければ Python を使った。 どちらもよく書くけど最近書いてないものだったので、結構ググり時間を消費してしまった。

感想

  • 途中の妨害タイムで、アンケートで答えた学校での成績や特技、将来の夢を晒されたのが(同意はしていましたが)やはりつらかった。解法で詰まっていて考えている時に将来の夢について聞かれてマイクを出されたため、適当な解答をしたのですが、めっちゃ態度悪い人みたいになってしまったかもしれず申し訳ない。
  • 表彰直前は「トイレに行きたい」以外のことを考えていなかったため、一言頼まれた時に何を言うか全く考えておらず、特技の「貧弱な語彙力」を発揮することとなってしまった。
  • 表彰の時にバックで僕の将来の夢が朗読されるのめちゃくちゃ恥ずかしいのでやめて欲しい… (tsunくんみたいに「アラブ人」と書いておけばよかった)
  • いざ writeup として文字起こししてみると大したことしてなくて恥ずかしい。クソコードなのは、焦る中動けばいいやと思って書いたものなので甘く見てください。
  • 僕はほぼ経験がない割に結構できて、楽しかった。問題が簡単だったのと、聡明なチームメイトの nkpoid のおかげですね。
  • nkpoid とうまく役割分担できてよかった。僕は特に得意分野があるわけでもなく、お互いその場のノリで「これやります」って言って解く感じでしたが、うまくいってよかった。
  • バイナリは strings 以外何も知らない状態で行ったので、very easy 以外だいたい nkpoid に任せることになってしまった。ありがとう。強くなりたい。
  • 1週間前に 某所のクソドライバのせいで Mac の環境を破壊したため macOS を再インストールしており、その影響で Wireshark やバイナリエディタが入っていない状態だった。Wireshark はその場で落とし、バイナリエディタは vim->:%!xxd で代用した。
  • ネットワークが恵まれていなかったため、苦労した。競技用のサーバーにアクセスする用の有線 LAN とインターネット利用向けの Wi-Fi を使わせてもらっていたが、有線 LAN 接続中は Wi-Fi に繋がっていてもインターネットにアクセスできなかったため、競技用サーバーにアクセスする必要のない時は有線 LAN を外すようにしていたが、頻繁に切り替えることとなり面倒だった。

以上です。 交通費もらえて (近所だけど) 京都に行けたし、楽しかったし、優勝して東京行けることになったので嬉しいです。ありがとうございました!