混淆#
原理#
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 に以下を追加する
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over 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 インターフェースは難読化できません
- その他、カスタマイズが必要なものもあります