はじめに
昨年10月に、テキサス州オースティンにてOWASP AppSec USA 2012が開催されました。OWASP(Open Web Application Security Project)とは、WebアプリケーションやWebサービスなどのセキュリティを対象としているボランティアによるコミュニティで、AppSecはそのカンファレンスです。
AppSecでは、さまざまなセキュリティ関連のセッションが行われていましたが、残念ながらAndroid向けのものはほとんどなく、いくつかあった内の1つが「Cracking the Code of Mobile Application」(講演者:Sreenarayan Ashokkumar)というセッションです。
AndroidやiOS、Windows Phoneといったプラットフォームで動作するアプリケーションを解析する方法について紹介するセッションで、サンプルアプリケーションのコードの中に含まれているパスワードや鍵を探しだすというデモを行なっていました。
今回はこのOWASPのセッションの内容をベースに、Androidアプリケーションの簡単な解析方法について紹介したいと思います。
apkファイルの内容
Androidアプリケーションは、apkと呼ばれるファイル形式で配布されています。apkという拡張子がついていますが、ZIP形式で圧縮されています。OWASPのセッションでは7-zipを使用してapkファイルを展開していましたが、7-zipを始めとするZIP形式に対応した一般的なアーカイバであれば展開することができます。
apkファイルを展開すると、図1に示すようなファイルが作成されます。
AndroidManifest.xmlはマニフェストファイル、META-INFディレクトリには署名関係のファイル、resディレクトリやresources.arscはリソースファイル、classes.dexはDalvik VMのバイトコードです。
このように、apkを一般的なアーカイバで展開して出てきたファイルはバイナリ化などされているため、テキストエディタなどで開いても読むことはできません。
解析に利用できるツール
アプリケーションの挙動を確かめるには、中身を確認する必要があります。しかし、各ファイルはバイナリ化されているため、単にapkを展開しただけでは確認することはできません。
そこで、OWASPのセッションでは、次のようなツールが紹介されました。
AndroidアプリケーションはJavaを使用して開発を行いますが、実行はDalvik VM上で行われます。よってJavaバイトコードとは異なり、Dalvik VM用のコードに変換されています。dex2jarはそのDalvik VMのコードをJava VMのコードに変換するツールです。Java DecompilerはJava VMのコードをJavaのソースコードに逆コンパイルするツールです。
これらのツールを使用して、apkファイルからdexファイル(Dalvik VMのバイトコード)を取り出し、それをjarファイルに変換して、Javaのソースコードに変換します。
また、この2つ以外にもいくつか便利なツールがあります。
apktoolは、バイナリ化されている各種データのデコードや、再パッケージができるツールです。また、androguardは逆アセンブルや逆コンパイルはもちろん、アプリケーション間の差分をとったり静的解析を行ったりすることができます。
解析方法
では、実際にいくつかツールの使い方を紹介します。インストール方法については、各ツールのサイトを参照してください。
dex2jarとJava Decompiler
dex2jarの使い方はとても簡単で、以下のように変換するapkファイルを指定します。
$ dex2jar.sh sample.apk
これだけで変換することができます。問題がなければsample_dex2jar.jarというファイルが新たに生成されているはずです。あとはもう1つのツールである、Java Decompilerでこのファイルを開きます(図2)。
オリジナルのJavaのコードと全く同じというわけにはいきませんが、比較的近い形でコードが再現されます。ただし、全てがこのようにうまく逆コンパイルできるわけではありません。場合によってはエラーが出てしまったり、もしくはコードが難読化されていると、とても読みにくいものになることもあります。
問題なく逆コンパイルできた場合、そこにあるのはお馴染みのJavaのコードなので、あとは読むだけになります。OWASPのセッションでは、ここでpasswordやkeyといったキーワードで検索して見つけていくということを行っていました。また、httpといったキーワードで検索すると、HttpUrlConnectionやHttpClientクラスといったものにマッチするので、外部と通信している部分のコードを探し出すことも可能です。