Android ProGuard代码混淆
2016-10-21 10:52
357 查看
关于混淆
代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。目前已经存在许多种功能各异的代码混淆器。众所周知,Java虽然是编译型的语言,但是由于Java编译后的字节码的抽象级别较高,因此它们较容易被反编译。为了防止我们的劳动成果被人窃取,我们通常会将Java程序混淆后打包,增大别人反编译时的难度。
当然,并不是混淆后,别人就无法反编译我们的程序了,否则这个混淆就可以改为加密了。代码混淆并不能真正阻止反向工程,只能增大其难度。因此,对于对安全性要求很高的场合,仅仅使用代码混淆并不能保证源代码的安全。混淆是将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字,然后进行打包,加大别人反编译我们的程序后的理解难度。
另外,因为混淆过程中会精简被混淆的类的类、变量、函数的名字,丢弃无用类和资源,因此混淆也会在一定程度上压缩编译后的文件大小。
混淆也会给我们自己带来一些问题。首先是时间成本上的增加,虽然混淆很简单,短则一两个小时,多则一两天就可以搞定,但是这个时间成本依旧存在。更重要的是,混淆会给我们的调试带来很大的困难,精简后的类、函数、变量名,给我们定位出错带来了一定的难度。对于支持反射的Java,代码混淆有可能与反射发生冲突,因此在与反射相关的类需要避免混淆。
Android的代码混淆默认使用ProGuard工具,在Android Developer上有相关介绍。
混淆配置步骤
以Android Studio为例。首先,我们需要在Module中的build.gradle中进行混淆配置。通常,我们在混淆时,只对release版本进行混淆,debug版本混淆很明显除了给自己调试增加难度外,没任何用。配置示例如下:
apply plugin: 'com.android.application' android { ... buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
minifyEnabled true即表示开启混淆。下一行
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'是指定多个混淆配置文件,
getDefaultProguardFile('proguard-android.txt')表示使用默认配置文件
proguard-android.txt,后面的
proguard-rules.pro即为我们自己编写的混淆配置文件。
在build.gradle指定的文件中,按照ProGuard语法编写混淆配置。
签名打包。
ProGuard语法
#指定代码的压缩级别0-7 -optimizationpasses 5 #是否使用大小写混合 -dontusemixedcaseclassnames #是否混淆第三方jar -dontskipnonpubliclibraryclasses #混淆时是否做预校验 -dontpreverify #混淆时是否记录日志 -verbose # 混淆时所采用的算法 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #从给定的文件中读取配置参数 -include {filename} #指定基础目录为以后相对的档案名称 -basedirectory {directoryname} #指定要处理的应用程序jar,war,ear和目录 -injars {class_path} #指定处理完后要输出的jar,war,ear和目录的名称 -outjars {class_path} #指定要处理的应用程序jar,war,ear和目录所需要的程序库文件 -libraryjars {classpath} #指定不去忽略非公共的库类。 -dontskipnonpubliclibraryclasses #指定不去忽略包可见的库类的成员。 -dontskipnonpubliclibraryclassmembers ## 保留选项 #保护指定的类文件和类的成员 -keep {Modifier} {class_specification} #保护指定类的成员,如果此类受到保护他们会保护的更好 -keepclassmembers {modifier} {class_specification} #保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。 -keepclasseswithmembers {class_specification} #保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除) -keepnames {class_specification} #保护指定的类的成员的名称(如果他们不会压缩步骤中删除) -keepclassmembernames {class_specification} #保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后) -keepclasseswithmembernames {class_specification} #列出类和类的成员-keep选项的清单,标准输出到给定的文件 -printseeds {filename} ## 压缩 #不压缩输入的类文件 -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 #保护给定的可选属性,例如LineNumberTable,LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. -keepattributes {attribute_name,...} #设置源文件中给定的字符串常量 -renamesourcefileattribute {string}
混淆示例
# 指定代码的压缩级别 -optimizationpasses 5 -dontusemixedcaseclassnames # 是否混淆第三方jar -dontskipnonpubliclibraryclasses -dontpreverify -keepattributes SourceFile,LineNumberTable -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -libraryjars libs/httpmime-4.1.3.jar -libraryjars libs/libammsdk.jar -libraryjars libs/fastjson-1.1.34.android.jar -libraryjars libs/commons-lang.jar -libraryjars libs/weibosdkcore.jar # webview + js # keep 使用 webview 的类 -keepclassmembers class com.goldnet.mobile.activity.InfoDetailActivity { public *; } # keep 使用 webview 的类的所有的内部类 -keepclassmembers class com.goldnet.mobile.activity.InfoDetailActivity$*{ *; } # 保持哪些类不被混淆 -keep class android.** {*; } -keep public class * extends android.view -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.pm -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService -keepattributes *Annotation* # 保持 native 方法不被混淆 -keepclasseswithmembernames class * { native <methods>; } # 保持自定义控件类不被混淆 -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclasseswithmembers class * { void onClick*(...); } -keepclasseswithmembers class * { *** *Callback(...); } # keep setters in Views so that animations can still work. # see http://proguard.sourceforge.net/manual/examples.html#beans -keepclassmembers public class * extends android.view.View { void set*(***); *** get*(); } # 保持枚举 enum 类不被混淆 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } # 保持 Parcelable 不被混淆 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } -keepclassmembers class **.R$* { public static <fields>; } # http client -keep class org.apache.http.** {*; } # keep 泛型 -keepattributes Signature # 新浪微博 -keep class com.sina.**{*;} # volley -dontwarn com.android.volley.jar.** -keep class com.android.volley.**{*;} # actionbarsherlock -dontwarn com.actionbarsherlock.** -keep class com.actionbarsherlock.**{*;} -dontwarn com.cairh.app.sjkh.** -keep class com.cairh.app.sjkh.**{*;}
混淆注意事项
根据代码混淆的原理(最主要的就是反射需要用到包名和类名方法名,而混淆会修改类名为其它无意义名字),Android代码在使用混淆使需要注意:Android系统组件应避免混淆。
被Jni调用的Java类要避免混淆。
所有的native方法不能被混淆
自定义View不应该被混淆。
枚举类不应该被混淆。
注解不应该被混淆
序列化的类(Parcelable)要避免混淆
利用GSON等解析工具解析Json的Bean类,不应该被混淆。
数据库驱动不应该被混淆。
aidl文件不能被混淆
Android建议不要混淆某些类,比如BackupAgent、ILicensingService等
在使用第三方工程的时候,一般会有说明混淆时候要注意哪些要避免混淆,按照其说明加入混淆配置中。
默认混淆
对于以上提到的注意事项,有些使用过混淆的朋友可能会觉得奇怪,我没有避免混淆Android系统组件,比如Activity,Service等等,为什么也没问题呢?这是因为在Android的默认配置中,已经做了相关配置,默认配置如下:# This is a configuration file for ProGuard. # http://proguard.sourceforge.net/index.html#manual/usage.html -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -verbose # Optimization is turned off by default. Dex does not like code run # through the ProGuard optimize and preverify steps (and performs some # of these optimizations on its own). -dontoptimize -dontpreverify # If you want to enable optimization, you should include the # following: # -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* # -optimizationpasses 5 # -allowaccessmodification # # Note that you cannot just include these flags in your own # configuration file; if you are including this file, optimization # will be turned off. You'll need to either edit this file, or # duplicate the contents of this file and remove the include of this # file from your project's proguard.config path property. -keepattributes *Annotation* -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgent -keep public class * extends android.preference.Preference -keep public class * extends android.support.v4.app.Fragment -keep public class * extends android.app.Fragment -keep public class com.android.vending.licensing.ILicensingService # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native -keepclasseswithmembernames class * { native <methods>; } -keep public class * extends android.view.View { public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); public void set*(...); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } -keepclassmembers class **.R$* { public static <fields>; } # The support library contains references to newer platform versions. # Don't warn about those in case this app is linking against an older # platform version. We know about them, and they are safe. -dontwarn android.support.**
欢迎转载,转载请保留文章出处。湖广午王的博客[http://blog.csdn.net/junzia/article/details/52879823]
相关文章推荐
- Android2.3 proguard介绍---代码混淆技术
- 如何混淆Android项目代码(ProGuard),防止反编译
- Proguard android代码混淆 防止反编译
- Android 4.0 ProGuard 代码混淆
- 使用ProGuard使你android代码保持混淆
- Eclipse+ADT对android apk 进行代码混淆(proguard)
- Android 2.3 代码混淆proguard技术介绍
- 在android中使用proguard混淆代码出现“Conversion to Dalvik format failed with error 1”错误的解决方法
- android使用proguard实现代码混淆
- 使用ProGuard使你android代码保持混淆
- Android 2.3 代码混淆proguard技术介绍
- Android 2.3 代码混淆proguard技术介绍 收藏
- 在android中使用proguard混淆代码出现“Conversion to Dalvik format failed with error 1”错误的解决方法
- 如何混淆Android项目代码(ProGuard)防止反编译
- 如何混淆Android项目代码(ProGuard),防止反编译
- Android杂谈--代码混淆及proguard一些错误处理
- Android 2.3 代码混淆proguard技术介绍
- Android 2.3 代码混淆proguard技术介绍
- Android 2.3 代码混淆proguard技术介绍
- 命令行编译android程序,欢迎探讨命令行如何使用proguard混淆优化代码