参考:ProGuard
目次
Gradle
Android のビルドについて(Gradle)を参照してください
ProGuard
ProGuard は、ソースコードの難読化と最適化を行うツールです。 apk に含まれる中間コードを逆コンパイルしても、プログラムの意味を人間にとって理解しにくい形にしておくことで、ソースコードの流出を防ぎます。 また、ソースコードの最適化において、不要なクラスを削除したり、インライン化を行ったりすることで、apk 自体のサイズが小さくなります。
設定ファイル
Android はデフォルトで、<sdk-root>/tools/proguard/proguard-android.txt
にある設定を読み、これを元に難読化・最適化をコントロールしています。
プロジェクト毎に固有の設定をしたい場合は、モジュールディレクトリ内にある proguard-release.txt
を編集します。
# MySampleClass の public なメンバを難読化しないようにする
-keepclassmembers class jp.mixi.sample.MySampleClass {
public *;
}
アノテーション
設定ファイルの代わりにアノテーションを用いて難読化の設定を行うこともできます。
アノテーションで難読化の設定をする場合は、アノテーション用の jar ファイルを導入する必要があります。
<sdk-root>/tools/proguard/examples/annotations/lib
の中に、annotations.pro
とannotations.jar
の 2 つのファイルがあります。それらをモジュールディレクトリ内のlibs
ディレクトリに配置します。
// クラス名を難読化しない
@Keep
public class MySampleClass {
public String mHogehoge; // このフィールドは難読化される
@KeepName
public String mFugafuga; // このフィールドは難読化されない
}
また、annotations.jar
へのパスを通すためにモジュールディレクトリ内の build.gradle
に以下の記述が必要です。
Android Studio 0.4.x 以降では、プロジェクトの新規作成時に libs
ディレクトリ配下の jar
ファイルに自動的にパスを通すように予め記述されているため、自身で定義しなくて大丈夫です。下記内容が build.gradle
に存在するか確認だけしましょう。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
主なアノテーションには以下のようなものがあります。
名称 | 説明 |
---|---|
Keep | クラス、メンバの削除、リネームを行わない |
KeepName | クラス、メンバの削除を行わない |
KeepClassMember | メンバの削除、リネームを行わない |
KeepClassMemberNames | メンバの削除を行わない |
実行の設定
プロジェクトを作成すると、モジュールディレクトリ内の build.gradle に以下の様な proguard に関する内容が記述されています。
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
buildTypes : デフォルトでは release 、debug の2種類が存在しており、独自に定義することも可能です。
runProguard : Proguard の有効、無効を指定します。プロジェクト作成時は false が設定されており無効となっています。
proguardFiles : Proguard の設定ファイルを指定します。また、getDefaultProguardFile() を使用することで、proguard-android.txt
のフルパスを取得しています。
実行後、proguard ディレクトリが作成され、難読化に用いられた情報や、難読化前と難読化後の対応関係を示すマッピング情報などが保存されます。保存されるファイルは以下のものがあります。
######dump.txt
apkファイル内の全クラスの内部構造が記述されています。
######mapping.txt
難読化される前後でクラス、メソッド、フィールド名がマッピングされたリストです。再トレースをするのに必要となる重要なファイルです。
######seeds.txt
難読化されなかったクラスとメンバーのリストです。
######aapt_rules.txt
layoutファイル、manifestファイルといった、リソースで定義されている、View、Acitivty に関連するクラス、メソッドなどで難読化対象外となったものがリスト化されています。
作成された proguard ディレクトリは、プロジェクト/モジュール/build/配下に格納され、内部は buildType ごとに分けられています。
実行
動作確認のため、debug build 時に proguard が有効になるように設定します。
buildTypes {
debug {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
buildTypes に debug を追加し、runProguard、proguardFiles を記述します。runProguard は true にします。
public String mHogehoge; // このフィールドは難読化される
@KeepName
public String mFugafuga; // このフィールドは難読化されない
検証のため、上記コードを追加し、debug build を実行します。プロジェクト名/モジュール名/build/proguard/debug に各種情報が格納され、以下の結果が得られます。
mapping.txt
jp.mixi.sample.proguard.MainActivity -> jp.mixi.sample.proguard.MainActivity:
java.lang.String mHogehoge -> r
java.lang.String mFugafuga -> mFugafuga
seeds.txt
jp.mixi.sample.proguard.MainActivity
jp.mixi.sample.proguard.MainActivity: java.lang.String mFugafuga
jp.mixi.sample.proguard.MainActivity: MainActivity()
mHogehoge が難読化され、mFugafuga は難読化されていないことがわかります。また、mFugafuga は難読化対象外となるため seeds.txt に追加されてます。
再トレース
難読化の影響は、コードそのものだけでなく、スタックトレースにも及びます。
このため、例外のスタックトレースの出力もまた、難読化された状態で出力されます。
例外のスタックトレースの内容を解析して、実際のコード上のどこで例外が発生したかを捉えたい場合、
ProGuard の retrace という機能を用いて、難読化を復元することができるようになっています。
ProGuard は、Android SDK の tools に含まれています。
この中の、proguard/bin/proguardgui.sh
を実行すると、GUI アプリケーションとして、ProGuard が起動します。
このアプリケーションの、ReTrace タブに、再トレースしたいスタックトレースと、難読化のマッピング情報を含むmapping.txt
を渡すと、再トレースが出来るようになります。
※ proguardgui.sh
の実行する際にエラー「 Unable to access jarfile /Applications/Android 」が発生した場合は、proguardgui.sh
を下記のように修正すると起動するようになります。
// 修正前
java -DsuppressSwingDropSupport=true -jar $PROGUARD_HOME/lib/proguardgui.jar "$@"
// 修正後
java -DsuppressSwingDropSupport=true -jar "$PROGUARD_HOME/lib/proguardgui.jar" "$@"