読者です 読者をやめる 読者になる 読者になる

Google CTF writeup

Google CTF

いつもの如く yharima チームで参加.
700 pts で 145 位だった.クソ難しかったという印象.
とりあえず自分が解いたやつを書きます.

In Recorded Conversation (25pts)

とりあえず落としてきた pcap を strings してみると,
IRC のログっぽい.適当にスクロールしているとフラグっぽい文字列が分割されてあったので,
順番に結合して投げただけ.

Ernst Echidna (50pts)

Web サイトをハッキングしてくれ,的な問題.
とりあえず適当に register してみてもよくわからない.
問題文に robots.txt みると良い的なことが書いてあるのでみると,
/admin が disallow されていた.
適当にログインしてアクセスしてみると

Sorry, this interface is restricted to administrators only

admin ユーザを作ってログインすれば良いのかと思い,
register してみると,

'admin' account already taken!

でダメ.

SQLi とかなんだろうかと思ったが,
一度自分が作ったアカウントで再度 register しても admin と同様のエラーにはならず,
普通にアカウントが作成できる.
ということは,アカウントの管理はしていないのではないか,と推測.
クッキーでも見てみるか,と思いみてみると md5-hash だと書いてある.
これは,ユーザ名の MD5 じゃないのかと思いとりあえず作ったユーザ名の MD5 をとってみると一致.
adminMD5 をとってクッキー差し替えて admin にアクセスしたらフラグが取れた.

Ill Intentions (150pts)

もっとスマートな解法があるので参考にしないことをおすすめします.

6時間くらい戦ってようやく解けた問題.解けたときはとても達成感と共に徒労感に襲われた.

apk がくるならとりあえず中身のソースコードを読んでみたくなるので,
以下の手順とツールデコンパイルして読んだ.

  • apk を unzip
  • dex2jar で class.dex を jar に変換
    • ./d2j-jar2dex.sh classes.dex
  • CFR で jar を ソースコードに変換
    • java -jar cfr_0_115.jar classes-dex2jar.jar --outputdir src

ざっとデコンパイルしたソースコードを読むと,
ブロードキャストすることでインテントが切り替わって,
切り替わったインテントでクリックすると native で書かれた関数を経由して,
なんらかの文字列(おそらくフラグ)を吐き出しているらしい,ということがわかった.

フラグを生成している部分の元の文字列は,リソースなどを追うとわかる.
ということは,頑張れば静的解析だけでなんとかなるんじゃないかと思い,
native で書かれた関数の実体である libhello-jni.so をみてみたが,
ちょっと解析する氣にはなれず動かしたいという方向に振れる.

ここから最高に迷走し始めるが,最終的には簡単にまとめると以下のように解いた.

1. apk を展開する
2. 展開した apk の AndroidManifest.xml を修正して指定したインテントを起動時に開くようにする
3. 展開した apk 内にあるコード(.smali)を弄ってフラグの変数を System.out.println するようにする
4. apk を再構築して適当に署名する
5. hack した apk をエミュで起動して ddms でログを監視する

もうゴリ押し以上の何者でもないという感じ(チームメンバーがほかの人の writeup を読んだ後にそう言われた).

まず apk の展開と再構築には apktool を使った.
どうやら wrapper script もある優しい仕様なので jar と一緒のディレクトリに転がして +x しておく.
展開自体は以下のコマンドで簡単にできる.

$ ./apktool d illintentions.apk

展開するとディレクトリが生成され,直下に AndroidManifest.xml がある.
現在は,起動時に MainActivity が起動するようになっているので,
MainActivityIsThisTheRealOne を入れ替えて IsThisTheRealOne を起動するようにする.
このとき android:labelandroid:name のどちらも入れ替えておいた(name だけでも良いかもしれない). これで, apk を再構築してインストールすると IsThisTheRealOne が起動するようになる.

これだけでは不十分なので, IsThisTheRealOne インテントの画面でクリックした際に,
System.out.println でフラグと思われる文字列を出力するようにする.
これは,展開した apk のディレクトリ内にある中間コード形式で保存されている smali を編集する.
smali/com/example/application/IsThisTheRealOne\$1.smali を開いて以下のように編集した.

@@ -144,9 +144,12 @@
     .line 34
     iget-object v5, p0, Lcom/example/application/IsThisTheRealOne$1;->this$0:Lcom/example/application/IsThisTheRealOne;

-    const-string v6, "ctf.permission._MSG"
+    const-string v9, "ctf.permission._MSG"

-    invoke-virtual {v5, v3, v6}, Lcom/example/application/IsThisTheRealOne;->sendBroadcast(Landroid/content/Intent;Ljava/lang/String;)V
+    invoke-virtual {v5, v3, v9}, Lcom/example/application/IsThisTheRealOne;->sendBroadcast(Landroid/content/Intent;Ljava/lang/String;)V
+
+    sget-object v8, Ljava/lang/System;->out:Ljava/io/PrintStream;
+    invoke-virtual {v8, v6}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

     .line 35
     return-void

const-string v6 は変数を表していて,もともとは "ctf.permission._MSG" が代入されている.
この v6 は元々出力したい文字列(フラグ)が代入されていて上書きされてしまっているので,v9 に変数名を変えておく.
後続の invoke-virtual {v5, v3, v6}メソッド呼び出しになっていて,
{v5, v3, v6} は引数部分になっている(呼び出し方は色々あり,第一引数に this のオブジェクトが必要,といった形式もあるので注意).
v6 は先ほど v9 に変えたので変更しておく.
続いて, sget-object v8, Ljava/lang/System;->out:Ljava/io/PrintStream; で System.out.println を実行する準備をする.
次の行で invoke-virtual {v8, v6} として, v6 を出力するようにしている.

以上の編集が終われば, apktool を使って再構築する.
再構築するコマンドは以下.

$ ./apktool b illintentions

これで展開していたディレクトリ直下に /dist ディレクトリが出来て,
その中に再構築された apk ができる.

しかし,このままエミュレータにはインストールできないので署名をする.

$ jarsigner -verbose -signedjar signed_illintentions.apk -keystore ~/.android/debug.keystore illintentions.apk androiddebugkey

keystore は androidSDK をインストールされると生成されるらしく,それを用いた.
パスワードは android なので上記実行後に求められるので入力する.

以上で,エミュレータで起動する準備は完了.
エミュレータを起動して adb を使って apk を転送する.
加えて, SDK ツールのどこかにログツールである ddms を起動しておく.

f:id:yharima:20160505003929p:plain

f:id:yharima:20160505003944p:plain

ddms にフラグが無事でました.

何問か相談したり,途中まで書いたコードから解いてくれたチームメンバーのブログを置いておきます.

Google Capture The Flag writeup | にろきのメモ帳