SECCON 2015 オンラインCTF に参加した

参加しました.

チーム名はp3r0zです.2000点で70位でした.
id:sukerutuloid:yueki1993@bonprosoftの4人チームでしたが,スタートから時間を取れている人がいなかったのが残念でした.私とsukerutuloは講義中にコソコソとやってはいましたが.

解けた問題

f:id:oboenikui:20151207161403p:plain
このうち私が解いたのは

  • Start SECCON CTF
  • SECCON WARS 2015
  • Reverse-Engineering Android APK 1
  • Exec dmesg
  • Decrypt it
  • Reverse-Engineering Android APK 2
  • Steganography 1

でした.(一部sukerutuloと一緒に解いたものも含みます)

Write Up

解いた問題の殆どが友利奈緒さん達によってWrite Upが書かれているので,解法が違うものだったりWrite Upが書かれていないもの以外はざっくりと書いていきます.

Start SECCON CTF

自分もコードを書くよりも手作業のほうが早かった.

SECCON WARS 2015

自分は動画をPhotoshopで読み込んで,全レイヤーのモードを「比較(明)」にしました.

Reverse-Engineering Android APK 1

apk解析は,私にとってはsmaliでは複雑なコードになると辛いのでdex2jarでデコンパイルしてjadJava Decompilerを使っています.
今回はlibcalc.soの実行結果であるcalc()とcnt=1000のときの計算だったので,calc()の結果を探して計算しました.
calc()の結果は,逆アセンブルするのも面倒だった(出先で環境が整ってなかった)ので,自分で新しくアプリを作って実行させて結果を得ました.

Exec dmesg

イメージファイルの中身はTiny Core Linuxを改変したものだったので,オリジナルのイメージを取ってきて比較しました.
dmesgはbusyboxのdmesgを呼び出していたのですが,本来なら呼び出せるはずが改変後は呼び出せず.オリジナルと比較するとdmesgがenfthに書き換えられていたのでそれを実行.出てきたテキストを目で探してフラグを入手.
sukerutuloくんにenfthのことだけ教えて託していたのに「見つからない」と言っていたので自分で探した所普通にありました.彼には目grep力の強化という次回までの目標ができたのでした.

Decrypt it

何かしらの文字列を用いてXORを取っていることはだいたいわかっていたのですが,コードを書くのが面倒だったので,以下のシェルスクリプトだけ書いて手打ちと目での比較でやりました.

#!/bin/bash
A=`/home/oboenikui/Documents/seccon/cryptooo/cryptooo $1`
set -- $A
echo $2 > tmp
base64 -d tmp > out
od -t x1 -w48 out

Reverse-Engineering Android APK 2

これは結構解けてないチームが多かったのでちょっと詳しく書きます.

まずはReverse-Engineering Android APK 1と同様にdex2jar→jad, JavaDecompilerで逆コンパイル
WelcomeActivityに,特定のuidで復号できるAESで暗号化された文字列が存在するので,そのuidを特定する必要があると判断.
(一応uidは0~fの16種の文字で構成され,鍵として使う部分の長さは16文字なので,16^16通り試せばできますw)
ヒントにハッキングが必要とあるので,SQLインジェクションかなと目星を付けました.
URLはJavaコード内に直書きされていて,login.phpとregister.phpがあることがわかりました.

まずはlogin側を調査すると,通信監視をしてemail, passwordは何かで暗号化してから送信していることが判明.暗号化の方法について調査することも考えましたが,面倒だったので放置で.Androidアプリで入力するだけでも十分攻撃可能と判断しました.
まずはemailとpasswordにシングルクォーテーションを入れた場合,email側に入れた時だけレスポンスにコンテンツデータが何も返ってこないことがわかったので,SQL文実行でエラーが起こるとそのようなレスポンスになると判断.
email:a, name:a, password:aのユーザーがすでにいたので,エラーを起こさないような文(『a' OR 'A'='A』や『a' AND name='a』など)を実行して,テーブル構造を推定.
結果,usersテーブルにemail, name, idは含まれるものの,password, uidに関する情報はないことが判明.passwordが一致しないことにはログインが通らないので,login側での攻撃は断念.
次に,register側を調査するも,自分のスマホではViewのXMLの不具合でアプリが落ちてしまいました.リクエストだけ送ろうとも思いましたが,loginとは別のキーで暗号化されていたため,それも断念.エミュレータ複数Androidバージョンで動かしたところ,どうも5.0では動かず,4.1では動くことが判明.そのままエミュレータで作業することに.
register側でも同様に攻撃を試みると,エスケープ処理が正しくされているINSERT文の後に脆弱なSELECT文を実行していることがわかったので,そこでusersテーブルのid=1から順に見ていくと,4にターゲットのユーザーが出現.(こちらはパスワードの一致判定をしていなかったので攻撃可能)
レスポンスにuidが記載されるため,そのuidを用いてはじめの文字列を復号化することで,フラグを入手しました.

Steganography 1

sukerutuloに「バイナリエディタでファイルを切り分けて」と言われたので,GIF, PNG, JPEG, BMPのヘッダを探して切り分けてフラグを発見.

おわりに

初参加でしたが,一部メンバーと協力して解いたことを考えても自分だけで1000点ちょいの活躍ができたので,来年はもっと取れるように頑張りたいです.
あとはチームメンバーの予定が合うことを祈ってます.

12/07 20:36追記

QR puzzle (Web)も解けました.(人力)
QR puzzle (Windows)と同様に動かせるようにスクリプトをJSコンソールで書き,複雑な問題はこちらで並べ替えるようにしました.
また,Hardになると,右上,左上,左下のマーカー(?)が空欄になるので,そこは要素の検証からimgのsrcを書き換えることで対応しました.
ちなみにQR読み込みソフトはQ太郎を用いました.

12/07 21:20追記

Find the prime numbersも解けました.
途中で時間が来てしまったので解き終わっていなかったのですが,解法としては一応答えの出るものだったようです.
まずはログの値の全てのc, o, hについてc * o - hの最大公約数をユークリッドの互除法で求め(= n * n),そこから1つの行について力技でxを求め,さらに力技でnumを求めました.計算時間が数分かかったので,もっと良い方法があったのかもしれないです.