一、 混淆的配置

1.1  AS 的混淆配置方法

1.打开对应Moudle下的build.gradle文件,然后将minifyEnabled设置为true,如下:buildTypes{   release{         minifyEnabled true//是否启动混淆 ture:打开   false:关闭         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'   }}minifyEnabled 为studio工程中默认混淆配置的开关,true为开启,反之关闭;proguardFiles getDefaultProguardFile:代表的是默认混淆的配置文件,文件中自定义了一系列的混淆,其中【proguard-android.txt】则是Google默认的一套混淆规则,该文件的实际路径为【SDK路径/tools/proguard/proguard-android.txt】;而proguard-rules.pro文件则是该moudle下的开发者自定义混淆规则,一般在moudle根目录PS:混淆后的映射对照表文件mapping.txt的对应目录为【/build/outputs/mapping/release/】,    它提供了混淆前后类、方法、类成员等的对照表,该文件比较重要,常常用于混淆代码堆栈的反解,编译快速分析定位问题。          # 抛出异常时保留代码行号 -keepattributes SourceFile,LineNumberTable2.编译Realsed版本已验证,在此过程中,IDE工具会在目录【/build/outputs/mapping/release/】产生混淆中间产物如下:dump.txt 描述APK文件中所有类的内部结构mapping.txt 提供混淆前后类、方法、类成员等的对照表,该文件比较重要,常常用于混淆代码堆栈的反解,编译快速分析定位问题seeds.txt 列出没有被混淆的类和成员usage.txt 列出被移除的代码我们可以根据 seeds.txt 文件检查未被混淆的类和成员中是否已包含所有期望保留的,再根据usage.txt 文件查看是否有被误移除的代码。3.混淆堆栈调试混淆后的类、方法名等等难以阅读,这固然会增加逆向工程的难度,但对追踪线上 crash 也造成了阻碍。我们拿到 crash 的堆栈信息后会发现很难定位,这时需要将混淆反解。在 /tools/proguard/  路径下有附带的的反解工具(Window 系统为 proguardgui.bat,Mac 或 Linux 系统为 proguardgui.sh )。这里以 Window 平台为例。双击运行 proguardgui.bat 后,可以看到左侧的一行菜单。点击ReTrace ,选择该混淆包对应的 mapping 文件(混淆后在 /build/outputs/mapping/release/ 路径下会生成 mapping.txt 文件,它的作用是提供混淆前后类、方法、类成员等的对照表),再将 crash 的 stack trace 黏贴进输入框中,点击右下角的ReTrace ,混淆后的堆栈信息就显示出来了。以上使用 GUI 程序进行操作,另一种方式是利用该路径下的 retrace 工具通过命令行进行反解,命令是retrace.bat|retrace.sh [-verbose] mapping.txt []例如:retrace.bat -verbose mapping.txt obfuscated_trace.txt注意事项:1) 所有在 AndroidManifest.xml 涉及到的类已经自动被保持,因此不用特意去添加这块混淆规则。(很多老的混淆文件里会加,现在已经没必要)2) proguard-android.txt 已经存在一些默认混淆规则,没必要在 proguard-rules.pro 重复添加


1.2  源码下的混淆配置方法

   在模块的Android.mk中配置   LOCAL_PROGUARD_ENABLED := full  obfuscation    //混淆开关配置,配置为disabled为关闭混淆   LOCAL_PROGUARD_FLAG_FILES := proguard.flags     //混淆规则文件配置PS: 如果需要调试方便话,最好在配置LOCAL_PROGUARD_ENABLED 时,增加obfuscation配置,     此时,系统会自定加入系统建议的【proguard_options 】规则以及生成中间产物【proguard_dictionary 】,这个文件如同android studio工程中的mapping文件。     源码混淆后的映射对照表文件【proguard_dictionary】的对用目录在【link_instr_intermediates_dir.COMMON】目录下,即【out/target/commons/obj/APPS/xxx模块_intermediates/】         1.proguard_dictionary 文件&mapping文件都需要在每一次realse版本时同版本一同保存,方便后面的调试,反解堆栈     2.请在目标模块的混淆规则中尽量增加如下规则,方面代码追踪。     # 抛出异常时保留代码行号 -keepattributes SourceFile,LineNumberTable系统源码混淆的配置文件:【模块混淆】android/build/make/core/package_internal.mkLOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED))ifndef LOCAL_PROGUARD_ENABLEDifneq ($(DISABLE_PROGUARD),true)    LOCAL_PROGUARD_ENABLED :=fullendifendififeq ($(LOCAL_PROGUARD_ENABLED),disabled)    # the package explicitly request to disable proguard.    LOCAL_PROGUARD_ENABLED :=endifproguard_options_file :=ifneq ($(LOCAL_PROGUARD_ENABLED),custom)ifeq ($(need_compile_res),true)    proguard_options_file := $(intermediates.COMMON)/proguard_optionsendif # need_compile_resendif # !customLOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)【java文件混淆】android/build/make/core/java.mk ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)# If no obfuscation, link in the instrmented package's classes.jar as a library.# link_instr_classes_jar is defined in base_rule.mklegacy_proguard_flags += -libraryjars $(link_instr_classes_jar)legacy_proguard_lib_deps += $(link_instr_classes_jar)else # obfuscation# If obfuscation is enabled, the main app must be obfuscated too.# We need to run obfuscation using the main app's dictionary,# and treat the main app's class.jar as injars instead of libraryjars.legacy_proguard_flags := -injars  $(link_instr_classes_jar) \    -outjars $(intermediates.COMMON)/proguard.$(LOCAL_INSTRUMENTATION_FOR).jar \    -include $(link_instr_intermediates_dir.COMMON)/proguard_options \    -applymapping $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \    -verbose \    $(legacy_proguard_flags)

混淆的原理

Java 是一种跨平台、解释型语言,Java 源代码编译成的class文件中有大量包含语义的变量名、方法名的信息,
很容易被反编译为Java 源代码。为了防止这种现象,我们可以对Java字节码进行混淆。混淆不仅能将代码中的类名、字段、方法名变为无意义的名称,
保护代码,也由于移除无用的类、方法,并使用简短名称对类、字段、方法进行重命名缩小了程序的size。

ProGuard由shrink、optimize、obfuscate和preverify四个步骤组成,每个步骤都是可选的,需要哪些步骤都可以在脚本中配置。参见ProGuard官方介绍。

压缩(Shrink): 侦测并移除代码中无用的类、字段、方法、和特性(Attribute)。
优化(Optimize): 分析和优化字节码。
混淆(Obfuscate): 使用a、b、c、d这样简短而无意义的名称,对类、字段和方法进行重命名。
上面三个步骤使代码size更小,更高效,也更难被逆向工程。
预检(Preveirfy): 在java平台上对处理后的代码进行预检。
 

混淆的语法

===========【常用的Proguard关键字及其描述】==================

Proguard关键字描述dontwarndontwarn是一个和keep可以说是形影不离,尤其是处理引入的library时.keep保留类和类中的成员,防止被混淆或移除keepnames保留类和类中的成员,防止被混淆,成员没有被引用会被移除keepclassmembers只保留类中的成员,防止被混淆或移除keepclassmembernames只保留类中的成员,防止被混淆,成员没有引用会被移除keepclasseswithmembers保留类和类中的成员,防止被混淆或移除,保留指明的成员keepclasseswithmembernames保留类和类中的成员,防止被混淆,保留指明的成员,成员没有引用会被移除... ...示例:(1)保留某个包下面的类以及子包-keeppublicclasscom.droidyue.com.widget.**(2)保留所有类中使用otto的public方法# Otto-keepclassmembers class ** {    @com.squareup.otto.Subscribe public *;    @com.squareup.otto.Produce public *;}(3)保留Contants类的BOOK_NAME属性-keepclassmembers classcom.example.admin.proguardsample.Constants {publicstatic java.lang.String BOOK_NAME;(4)dontwarn:引入的library可能存在一些无法找到的引用和其他问题,在build时可能会发出警告,如果我们不进行处理,通常会导致build中止.因此为了保证build继续,我们需要使用dontwarn处理这些我们无法解决的library的警告.#比如关闭Twittersdk的警告,我们可以这样做-dontwarncom.twitter.sdk.**

===========【Proguard通配符及其描述】===============

 

Proguard通配符描述匹配类中的所有字段匹配类中所有的方法匹配类中所有的构造函数*匹配任意长度字符,不包含包名分隔符(.)**匹配任意长度字符,包含包名分隔符(.)***匹配任意参数类型......


===========【Proguard语法如下】=================

[保持命令] [类] {    [成员] }“类”代表类相关的限定条件,它将最终定位到某些符合该限定条件的类。它的内容可以使用:具体的类访问修饰符(public 、protected 、private )通配符* ,匹配任意长度字符,但不含包名分隔符(.)通配符** ,匹配任意长度字符,并且包含包名分隔符(.)extends ,即可以指定类的基类implement ,匹配实现了某接口的类$,内部类“成员”代表类成员相关的限定条件,它将最终定位到某些符合该限定条件的类成员。它的内容可以使用:匹配所有构造器匹配所有域匹配所有方法通配符* ,匹配任意长度字符,但不含包名分隔符(.)通配符** ,匹配任意长度字符,并且包含包名分隔符(.)通配符*** ,匹配任意参数类型… ,匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。访问修饰符(public 、protected 、private )举个例子,假如需要将name.huihui.test 包下所有继承Activity 的public 类及其构造函数都保持住,可以这样写:-keep public class name.huihui.test.** extends Android.app.Activity {    }


===========【哪些不应该混淆】===========

使用了自定义控件那么要保证它们不参与混淆使用了枚举要保证枚举不被混淆对第三方库中的类不进行混淆运用了反射的类也不进行混淆使用了 Gson 之类的工具要使 JavaBean 类即实体类不被混淆在引用第三方库的时候,一般会标明库的混淆规则的,建议在使用的时候就把混淆规则添加上去,免得到最后才去找有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因和第一条一样Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常使用的四大组件,自定义的Application* 实体类JNI中调用的类Layout布局使用的View构造函数(自定义控件)、android:onClick等

===========【常用的自定义混淆规则】===========
 

不混淆某个类-keep public class name.huihui.example.Test { *; }不混淆某个包所有的类-keep class name.huihui.test.** { *; }不混淆某个类的子类-keep public class * extends name.huihui.example.Test { *; }不混淆所有类名中包含了“model”的类及其成员-keep public class **.*model*.** {*;}不混淆某个接口的实现-keep class * implements name.huihui.example.TestInterface { *; }不混淆某个类的构造方法-keepclassmembers class name.huihui.example.Test {   public (); }不混淆某个类的特定的方法-keepclassmembers class name.huihui.example.Test {   public void test(java.lang.String); }

 

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. Android(安卓)面试准备进行曲(Android(安卓)基础知识)v1.1
  6. android移植(0)-热身
  7. 【Android(安卓)开发教程】辅助方法
  8. android PhoneGap 入门
  9. Android(安卓)注解的应用

随机推荐

  1. hcidump用法
  2. Android(安卓)TV -1.1- Get Started with
  3. android百度地图
  4. androidstudio加载项目问题
  5. android SharedPreferences初步
  6. Android(安卓)Tabs 中使用listview,mapvie
  7. Building the Android(安卓)JDBC Driver
  8. 【Android动画九章】-帧动画
  9. Android(安卓)Binder IPC
  10. Android(安卓)支持的媒体格式(音频,视频,