ユーザ用ツール

サイト用ツール


ctf:lesson:第6回

差分

この文書の現在のバージョンと選択したバージョンの差分を表示します。

この比較画面にリンクする

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
ctf:lesson:第6回 [2018/07/03 11:27]
sei0o 仮!w
ctf:lesson:第6回 [2018/08/15 16:49] (現在)
ライン 1: ライン 1:
-** 事前準備+# 第6回資料 
 + 
 +- 2018/7/4 
 +- 暑い 
 +- 北海道楽しかった…お土産あるよ… 
 +- 今回の内容:​ Androidアプリを解析してみる,​ ソースコードを読むのに慣れる 
 + 
 +## 事前準備
  
 - 以下をインストールしておいてください - 以下をインストールしておいてください
- - dex2jar→https://​github.com/​pxb1988/​dex2jar/​releases/​tag/​2.0 からdex-tools-2.0.zipをダウンロード、展開 +- dex2jar→[https://​github.com/​pxb1988/​dex2jar/​releases/​tag/​2.0](https://​github.com/​pxb1988/​dex2jar/​releases/​tag/​2.0) ​からdex-tools-2.0.zipをダウンロード、展開 
- - jad→https://​varaneckas.com/​jad/​ 普通のLinuxなら「Jad 1.5.8e for Linux on Intel platform 」で大丈夫なはず +- jad→[https://​varaneckas.com/​jad/​](https://​varaneckas.com/​jad/​) ​普通のLinuxなら「Jad 1.5.8e for Linux on Intel platform 」で大丈夫なはず 
- - sqlitebrowser→https://​sqlitebrowser.org にOS/​distroごとにインストール方法が書かれています+- sqlitebrowser→[https://​sqlitebrowser.org](https://​sqlitebrowser.org) ​にOS/​distroごとにインストール方法が書かれています 
 + 
 +## 扱うファイル 
 + 
 +- BSideSF CTF 2017: pinlock (150点) のファイルを題材にします 
 +- [https://​github.com/​ctfs/​write-ups-2017/​tree/​master/​bsidessf-ctf-2017/​reversing/​pinlock-150](https://​github.com/​ctfs/​write-ups-2017/​tree/​master/​bsidessf-ctf-2017/​reversing/​pinlock-150) から pinstore.apk をダウンロード 
 +- このアプリでは起動時にPIN(パスコード)を打つ必要があります、そのPINを見つけてみましょう 
 + 
 +## APKを見てみる 
 + 
 +- `.apk`という拡張子・形式は初めて見ると思います 
 + - Android端末で動作するアプリの形式です 
 +- バイナリを見てみよう 
 + 
 +```bash 
 +$ xxd pinstore.apk | head -n 5 
 +0000000: 504b 0304 1400 0808 0800 457b 4a4a 82d1  PK........E{JJ.. 
 +0000010: 5b22 ec02 0000 2808 0000 1300 0400 416e  ["​....(.......An 
 +0000020: 6472 6f69 644d 616e 6966 6573 742e 786d  droidManifest.xm 
 +0000030: 6cfe ca00 00ad 543d 6fd4 4010 7d3e df05  [email protected]}>​.. ​                                                                    
 +0000040: 1f26 e4f2 fd71 49a0 a088 90ce 0488 00d1  .&​...qI......... 
 +``` 
 + 
 + - 先頭(シグネチャ)に注目→実は**.apk = .zip** 
 +- 展開してみる 
 + 
 +```bash 
 +$ unzip pinstore.apk 
 +...snip... 
 +$ ls 
 +AndroidManifest.xml ​ assets/ ​ classes.dex ​ META-INF/ ​ pinstore.apk ​ res/  resources.arsc 
 +``` 
 + 
 + - `assets/​`→アセット,​ 画像とか音声とかデータ 
 + - `res/​`→いろいろなアプリで使いまわされるデータ 
 + - `META-INF/` `AndroidManifest.xml` →アプリに関する情報(識別子、バージョンetc) 
 + - `resources.arsc`→メッセージなどに使う文字列 
 + - `classes.dex`→動作させるための`.jar`(後述)が入っているDEX形式のファイル 
 +  - ここを中心に解析していきます 
 + 
 +## あなたとJava、いますぐダウンロード 
 + 
 +- 踏み込む前に、少し**Java**について書いておきます 
 +- Java言語は知っていますか? 
 +- 実行の流れに特徴がある 
 + - 普通のコンパイラではソースコードを入れると機械語を吐き出します 
 + - Javaは**JVM (Java Virtual Machine)**を利用しているので、少し実行の仕方が違います 
 +  - Minecraftやる人ならJDKとかJREとかダウンロードしたことがあると思いますが、あれらの中にJVMが含まれています 
 +  - まず、ソースコードを部分ごとに`.class`という拡張子を持つ**バイトコード**に変換(コンパイル)します 
 +  - 次に、実行環境のJVMでバイトコードを機械語に変換&実行(JITコンパイル)して、実際にプログラムが動きます 
 +  - どうしてこんなまどろっこしいことをするのかは「Write Once, Run Anywhere」で検索すると見つかるかもしれません 
 +- AndroidのアプリはJVM系の言語で書かれることが多いです 
 + - 「もともとの言語が異なっても、JVMで動くバイトコードさえ出力できればあとは同じじゃん」という発想 
 + - 実際、Androidの公式の開発言語はKotlinという別のJVM言語です 
 + - スピードが要求される場面ではNDK (Native Development Kit)を使ってC/​C++で書くこともあります 
 + 
 +## APKのソースコードを見てみよう 
 + 
 +- dex2jarを使って`classes.dex`内の`.class`(→バイトコード)を見てみます 
 + 
 +```bash 
 +$ /​path/​to/​dex2jar-2.0/​d2j-dex2jar.sh classes.dex 
 +``` 
 + 
 +- バイトコードを配布用にまとめたのが`.jar`ファイルで、これも正体はZIPです 
 + 
 +```bash 
 +$ unzip classes-dex2jar.jar 
 +$ cd pinlock/​ctf/​pinlock/​com/​pinstore/​ 
 +$ ls  
 +BuildConfig.class ​       MainActivity.class ​ R.class ​ ... 
 +``` 
 + 
 +- バイトコードをそのまま読んで動作を解析しても良いのですが、もっとラクな方法を紹介します 
 +- **デコンパイル** (decompile) です 
 + - コンパイルの逆 
 + - 機械語・アセンブラから元のソースコードを復元するのは難しい(らしい)のですが、バイトコードからだとわりとサクっとできてしまいます 
 +- jadを使ってデコンパイルしてみましょう 
 + - `*.class`のようにするとそこにあるすべての`.class`ファイルを指定できます 
 + 
 +```bash 
 +$ /​path/​to/​jad *.class 
 +``` 
 + 
 + - `.jad`がいろいろ生成されますね、これがデコンパイル結果です 
 + 
 +## いざ解析 
 + 
 +- `MainActivity.jad`を読んでみましょう 
 + - Androidでは、大体の処理はここから始まります 
 + 
 +```java 
 +public void onClick(View view) { 
 +    String s; 
 +    String s2; 
 +    s2 = pinEditText.getText().toString();​ 
 +    view = null; 
 +    s = null; 
 +    String s1 = (new DatabaseUtilities(getApplicationContext())).fetchPin();​ 
 +    view = s1; 
 +_L1: 
 +    s1 = CryptoUtilities.getHash(s2);​ 
 +    s = s1; 
 +_L2: 
 +    Object obj; 
 +    if(view.equalsIgnoreCase(s)) { 
 +        view = new Intent(MainActivity.this,​ pinlock/​ctf/​pinlock/​com/​pinstore/​SecretDisplay);​ 
 +        view.putExtra("​pin",​ s2); 
 +        startActivity(view);​ 
 +        return; 
 +    } else { 
 +        pinEditText.setText(""​);​ 
 +        Toast.makeText(MainActivity.this,​ "​Incorrect Pin, try again",​ 1).show();​ 
 +        return; 
 +    } 
 +``` 
 + 
 + - 入力された文字列(PIN)のハッシュと`DatabaseUtilities`から取得した文字列を比較していますね 
 + - 一致していれば`SecretDisplay`にpinを渡して処理を移動しています 
 +- 次に`SecretDisplay.jad`を見てみましょう 
 + 
 +```java 
 +String s = getIntent().getStringExtra("​pin"​);​ 
 +try { 
 +    DatabaseUtilities databaseutilities = new DatabaseUtilities(getApplicationContext());​ 
 +    textview.setText((new CryptoUtilities("​v1",​ s)).decrypt(databaseutilities.fetchSecret()));​ 
 +} catch (Exception exception) { 
 +    Log.e("​Pinlock",​ "​exception",​ exception);​ 
 +
 +Toast.makeText(bundle,​ s, 1); 
 +``` 
 + 
 + - 受け取ったpinで`CryptoUtilities`なるものを生成してから、`DatabaseUtilities`で取り出してからdecrypt(=復号・解読)していますね 
 + - 解読結果を表示しているみたいです 
 + 
 +- おおまかな流れが掴めたので、`DatabaseUtilities`の内容も読んでみましょう 
 +- `DatabaseUtilities` 
 + 
 +```bash 
 +public String fetchPin() { // MainActivityから呼び出される 
 +    openDB(); 
 +    Cursor cursor = db.rawQuery("​SELECT pin FROM pinDB",​ null); // pinDBテーブルからデータを取り出す 
 +    ... 
 +    return s; 
 +
 +  
 +public String fetchSecret() { // SecretDisplayから呼び出される 
 +    openDB(); 
 +    Cursor cursor = db.rawQuery("​SELECT entry FROM secretsDBv1",​ null); // secretsDBv1テーブルからデータを取り出す 
 +    ... 
 +    return s; 
 +
 +  
 +... 
 +  
 +private static String dbName = "​pinlock.db";​ 
 +private static String pathToDB = "/​data/​data/​pinlock.ctf.pinlock.com.pinstore/​databases/";​ 
 +``` 
 + - データベースからいろいろ読み出しているみたいです 
 + 
 +## データベースを見てみる 
 + 
 +- `pinlock.db`というのがデータベースのファイルっぽいので、中身のデータを取り出してみましょう 
 + - `find`コマンドでファイルを検索できます 
 + 
 +```bash 
 +$ find -name pinlock.db 
 +./​assets/​pinlock.db 
 +$ sqlitebrowser ./​assets/​pinlock.db & 
 +``` 
 + 
 + - Browse DataからTableを選択するとデータが表示できます 
 + - ![](https://​i.gyazo.com/​0fdf5546e6a2fc8b7f1f696170c43f21.png) 
 + 
 +## ハッシュ関数について 
 + 
 +- 暗号化について前少し話しましたが、ハッシュ関数は「復号できない暗号化」です 
 +- ハッシュ関数は「ある値を入れると、それに応じたハッシュ値を出力する」ものです 
 + - 入力が異なれば、必ずハッシュ値は異なったものになる 
 + - ハッシュ値から入力を推定することはできない 
 +- SHA256, SHA1, MD5など種類があります 
 + 
 +- どう便利なのかイマイチわからないので、ざっくり認証での例を紹介します 
 + - パスワードhogehogeを持つユーザーのデータを保存したいとします 
 +  - このとき、hogehogeという文字列をそのまま保存すると、データが流出した際にパスワードが漏れてしまいます 
 +  - 代わりに、hogehogeをハッシュ関数に入力したものを保存することにします 
 +   - ハッシュ関数(SHA256)の出力→4c716d4cf211c7b7d2f3233c941771ad0507ea5bacf93b492766aa41ae9f720d 
 + - このユーザーでログインしたいときは、ユーザーが入力したパスワードをハッシュ関数に入力します 
 +  - 入力したパスワードが正しければ、ハッシュ値は4c716d4cf211c7...となって上と合致します 
 +  - 誤っていれば、「入力が異なれば、必ずハッシュ値は異なったものになる」という性質より、上のハッシュ値とは合致しません 
 + - 参考: [http://​www.nttdata.com/​jp/​ja/​insights/​blog/​20170914.html](http://​www.nttdata.com/​jp/​ja/​insights/​blog/​20170914.html) 
 + 
 +## PINを解読しよう 
 + 
 +- でも、「password」や「114514」といった有名・簡単(数字だけ・短い)な文字列に対するハッシュ値はまとめられている 
 +- [CrackStation](http://​crackstation.net/​) にハッシュ値を入れてみましょう 
 +- ![](https://​i.gyazo.com/​44651e65337a2d280227845867f4b313.png) 
 +- PINは7498ですね! 
 + 
 +## ソースコードを読むときのコツ 
 + 
 +- ある関数がどこから呼び出されたり、どこに定義されているかわからない→ファイルを横断した検索を活用しましょう 
 + - VSCodeならサイドバーの虫眼鏡を押すと検索できます 
 + - コマンドラインならgrepや[ripgrep](https://​github.com/​BurntSushi/​ripgrep)を使いましょう 
 +- ctagsなどもありますが詳しくないのでわかりません 
 + 
 +## 発展 
 + 
 +- これはCTFの問題ですが、FLAGが出てきていません→実は問題を解いたのではなくて、PINを見つけるのはそのステップの一つ 
 + - あとは自分でやってみてください、[ここ](https://​scrapbox.io/​sei0opub/​BSides_San_Francisco_CTF_2017:​_pinlock)がヒントになるかも 
 +- Wiki書いてくれるととても嬉しい 
 + - 僕が嬉しくなるのはどうでもいいんですが、将来内容を思い出すとき・誰かに教えるときにそういうメモが役立ったりします 
 +- バイトコード 
 + - バイトコードの中身はアセンブラと高級言語の中間みたいな感じです 
 + - 興味のあるひとには[Javaのクラスファイルをjavapとバイナリエディタで読む](https://​dev.classmethod.jp/​server-side/​java/​classfile-reading/​)がいいかも 
 + - C#​も同じ方式を採用しています 
 +- 今回はSQLiteという種類のデータベースでしたが、他にもいろいろあります 
 + - 途中にあった`SELECT * FROM pinDB`などは**SQL**言語で書かれたデータベースを操作するためのコードです 
 + - PostgreSQL, MySQL, mongoDBなどが有名 
 +- Android 
 +- [awesome-mobile-CTF](https://​github.com/​xtiankisutsa/​awesome-mobile-CTF/​blob/​master/​README.md) おもしろそうなスマホ系の問題がたくさん載っています、一緒にやろう! 
 +- ハッシュ関数はbitcoinのマイニングにも使われてたりします
ctf/lesson/第6回.txt · 最終更新: 2018/08/15 16:49 (外部編集)