混淆#
原理#
Java はクロスプラットフォームのインタプリタ型言語であり、Java ソースコードは中間の「バイトコード」にコンパイルされ、class ファイルに保存されます。クロスプラットフォームの必要性から、Java バイトコードには多くのソースコード情報が含まれており、変数名やメソッド名などを通じて変数やメソッドにアクセスします。これらのシンボルには多くの意味情報が含まれており、簡単に Java ソースコードに逆コンパイルされる可能性があります。この現象を防ぐために、Java 混淆器を使用して Java バイトコードを混淆することができます。
混淆とは、公開されたプログラムを再構成し処理することで、処理後のコードが処理前のコードと同じ機能を果たすようにし、混淆されたコードは逆コンパイルが非常に難しく、逆コンパイルに成功してもプログラムの真の意味を理解するのが難しい状態にすることです。混淆されたプログラムコードは、元のファイル形式と命令セットに従い、実行結果も混淆前と同じですが、混淆器はコード内のすべての変数、関数、クラスの名前を短い英字の記号に変更します。相応の関数名やプログラムコメントが欠如している場合、逆コンパイルされても読みづらくなります。また、混淆は不可逆的であり、混淆の過程で正常な動作に影響しない情報が永続的に失われます。この情報の喪失により、プログラムはさらに理解しにくくなります。
混淆器の役割はコードを保護するだけでなく、コンパイル後のプログラムサイズを縮小することにもあります。上記の理由から、変数や関数名を短縮し、一部の情報を失うことで、コンパイル後の jar ファイルのサイズは約 25%削減され、これは現在コストが高い無線ネットワークの伝送において一定の意義があります。
语法#
-include {filename} 指定されたファイルから設定パラメータを読み込む
-basedirectory {directoryname} 基本ディレクトリを指定し、以後の相対ファイル名を指定
-injars {class_path} 処理するアプリケーションのjar,war,earおよびディレクトリを指定
-outjars {class_path} 処理後に出力するjar,war,earおよびディレクトリの名前を指定
-libraryjars {classpath} 処理するアプリケーションのjar,war,earおよびディレクトリに必要なライブラリファイルを指定
-dontskipnonpubliclibraryclasses 非公開のライブラリクラスを無視しないよう指定
-dontskipnonpubliclibraryclassmembers パッケージ可視のライブラリクラスのメンバーを無視しないよう指定
保留オプション
-keep {Modifier} {class_specification} 指定されたクラスファイルとクラスのメンバーを保護
-keepclassmembers {modifier} {class_specification} 指定されたクラスのメンバーを保護し、このクラスが保護されている場合はより良く保護される
-keepclasseswithmembers {class_specification} 指定されたクラスとクラスのメンバーを保護するが、すべての指定されたクラスとクラスメンバーが存在することが条件
-keepnames {class_specification} 指定されたクラスとクラスのメンバーの名前を保護(圧縮ステップで削除されない場合)
-keepclassmembernames {class_specification} 指定されたクラスのメンバーの名前を保護(圧縮ステップで削除されない場合)
-keepclasseswithmembernames {class_specification} 指定されたクラスとクラスのメンバーの名前を保護し、すべての指定されたクラスメンバーが出席する場合(圧縮ステップ後)
-printseeds {filename} クラスとクラスのメンバー-keepオプションのリストを列挙し、標準出力を指定されたファイルに出力
圧縮
-dontshrink 入力されたクラスファイルを圧縮しない
-printusage {filename}
-whyareyoukeeping {class_specification}
最適化
-dontoptimize 入力されたクラスファイルを最適化しない
-assumenosideeffects {class_specification} 最適化時に指定されたメソッドに副作用がないと仮定
-allowaccessmodification 最適化時に修飾子のあるクラスとクラスのメンバーへのアクセスと変更を許可
混淆
-dontobfuscate 入力されたクラスファイルを混淆しない
-printmapping {filename}
-applymapping {filename} マッピングを再利用して混淆を増加
-obfuscationdictionary {filename} 指定されたファイル内のキーワードを混淆メソッドの名前として使用
-overloadaggressively 混淆時に侵入的なオーバーロードを適用
-useuniqueclassmembernames 一意の混淆クラスのメンバー名を決定して混淆を増加
-flattenpackagehierarchy {package_name} すべてのリネームされたパッケージを再包装し、指定された単一のパッケージに配置
-repackageclass {package_name} すべてのリネームされたクラスファイルを再包装し、指定された単一のパッケージに配置
-dontusemixedcaseclassnames 混淆時にさまざまなクラス名を生成しない
-keepattributes {attribute_name,...} 指定されたオプション属性を保護、例えばLineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-renamesourcefileattribute {string} ソースファイル内の指定された文字列定数を設定
文件#
mapping.txt
混淆前後のコードの対照表で、これを使用してログ調査や逆コンパイルなどを行います。
dump.txt
apk 内のすべての class ファイルの内部構造を説明します。
seed.txt
混淆されていないクラスとメンバーのリストを列挙します。
usage.txt
ソースコード内で削除され、apk に存在しないコードのリストを列挙します。
常见问题#
1、Proguard がエラーコードで返された
-
proguard のバージョンを更新する
-
android-support-v4 は混淆しない
-
必要なライブラリを追加する
2、gson パッケージを使用してデータを解析する際に、missing type parameter 例外が発生する
- proguard.cfg に追加
-dontobfuscate
-dontoptimize
- proguard.cfg に追加
# デフォルトではそのような情報を削除するため、すべてを保持するように設定します。
-keepattributes Signature
# Gson特有のクラス
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Gsonを介してシリアル化/デシリアル化されるアプリケーションクラス
-keep class com.google.gson.examples.android.model.** { *; }
3、型変換エラー
-keepattributes Signature
4、NullPointerException
混淆が関連するクラスとメソッドをフィルタリングする
5、java.lang.NoSuchMethodError
関連するメソッドがなく、メソッドが混淆されているため、混淆が関連するメソッドをフィルタリングすればよい
バグ調査:http://proguard.sourceforge.net/index.html#manual/troubleshooting.html
注意#
- リフレクションは混淆できません
- システムインターフェースは混淆できません
- Jni インターフェースは混淆できません
- その他の特別なカスタマイズが必要なものもあります