Android ProGuard代码混淆解析

1、代码混淆配置

如下图,默认情况下,混淆是关闭的,我们只需要将minifyEnabled置为true就可以开启混淆了。

这里写图片描述

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

其中:
minifyEnabled表示是否开启混淆
proguardFiles用于选定混淆配置文件,getDefaultProguardFile(‘proguard-android.txt’) 方法可从 Android SDK tools/proguard/ 文件夹获取默认的 ProGuard 设置,proguard-rules.pro 文件用于添加自定义 ProGuard 规则。默认情况下,该文件位于模块根目录(build.gradle 文件旁)。

需要注意的是,上面加载了两个混淆配置文件,一个是默认的,一个是自定义的,所以这里告诉我们我们可以同时指定多个混淆配置文件,另外我们还可以分开来写,如下:

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt')
    proguardFiles 'proguard-rules.pro'
    }
}

为啥进行了上述的配置就可以进行代码的混淆呢?

在$android-sdk-linux/tools/proguard/lib/目录下面有一个proguard.jar,我们代码混淆的工作其实就是这个jar完成的。

Linux或者Mac平台下,在android-sdk-linux/tools/proguard/bin/文件夹中有两个脚本文件,他们就是运行这个jar文件的脚本,proguard.sh是使用命令行操作的混淆脚本,proguardgui.sh是带有可视化操作界面的混淆脚本,背后实质运行的都是这个proguard.jar工具。

所以我们如果想单独对某一个jar文件进行混淆,其实也是可以的,我们直接运行这个工具就可以操作了。

2、混淆规则

在Android SDK tools/proguard/ 文件夹下默认有三个文件:

(1)、proguard-android.txt 默认的Proguard配置文件(未优化)
(2)、proguard-android-optimize.txt 默认的Proguard配置文件(已优化)
(3)、proguard-project.txt 默认的用户定制Proguard配置文件。

下面我们来查看下proguard-android.txt中的默认配置规则

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

#表示混淆时不使用大小写混合类名 
-dontusemixedcaseclassnames
#表示不跳过library中的非public的类
-dontskipnonpubliclibraryclasses
#表示打印混淆的详细信息
-verbose

# 表示不进行优化
-dontoptimize
表示不进行预校验
-dontpreverify
# 表示对注解中的参数进行保留
-keepattributes *Annotation*
#表示不混淆类ILicensingService
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

#表示不混淆任何包含native方法的类的类名以及native方法名
-keepclasseswithmembernames class * {
    native <methods>;
}

#表示不混淆任何一个View中的setXxx()和getXxx()方法
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# 表示不混淆Activity中参数是View的方法
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# 表示不混淆枚举中的values()和valueOf()方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#表示不混淆Parcelable实现类中的CREATOR字段
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

#表示不混淆R文件中的所有静态字段
-keepclassmembers class **.R$* {
    public static <fields>;
}

#表示对android.support包下的代码不警告
-dontwarn android.support.**

#不混淆Keep注解类
-keep class android.support.annotation.Keep

#不混淆带有Keep注解的类
-keep @android.support.annotation.Keep class * {*;}

#不混淆带有Keep注解的成员方法以及类名
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

#不混淆带有Keep注解的成员变量以及类名
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

#不混淆带有Keep注解的构造方法以及类名
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

上面可以看到,对于Keep注解的类、成员变量、成员方法是不会被混淆的,因此我们可以使用@Keep注解来防止混淆

例如:

//防止混淆类
@Keep
public class Person {}

//防止混淆变量
@Keep
public String name;

//防止混淆方法
@Keep
public int getAge(){}

下面对关键词和通配符进行一个总结

这里写图片描述

这里写图片描述

关于优化的几个规则

-dontoptimize 
关闭优化项,如果没有这项默认优化项是开启的

-optimizations optimization_filter 
根据optimization_filter指定要优化的文件

-optimizationpasses n  
优化数量 n 

-assumenosideeffects class_specification 
在优化阶段,ProGuard会将指定的class_specification代码移除。这里可以用做Log代码的移除

-assumenosideeffects class android.util.Log {
    public static *** e(...);
    public static *** d(...);
    public static *** w(...);
    public static *** v(...);
    public static *** i(...);
}



-allowaccessmodification
优化时允许访问并修改类和类的成员的访问修饰符,可能作用域会变大。

-mergeinterfacesaggressively
合并接口,即使它们的实现类未实现合并后接口的所有方法。

理解了上面优化项之后,我们就可以看看proguard-android-optimize.txt和proguard-android.txt到底有什么区别,他们的区别其实就是在优化项上,对比下他们里面的内容,我们发现proguard-android.txt包含下面内容:

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize

-dontoptimize

# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

上面注释翻译如下:关闭优化功能,不会进行优化,另外,如果你想开启优化功能,建议使用proguard-android-optimize.txt配置文件

可以看到在proguard-android.txt明确将优化项关闭了。

下面来看看proguard-android-optimize.txt文件

# Optimizations: If you don't want to optimize, use the
# proguard-android.txt configuration file instead of this one, which
# turns off the optimization flags.  Adding optimization introduces
# certain risks, since for example not all optimizations performed by
# ProGuard works on all versions of Dalvik.  The following flags turn
# off various optimizations known to have issues, but the list may not
# be complete or up to date. (The "arithmetic" optimization can be
# used if you are only targeting Android 2.0 or later.)  Make sure you
# test thoroughly if you go this route.
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification

# The remainder of this file is identical to the non-optimized version
# of the Proguard configuration file (except that the other file has
# flags to turn off optimization).

上面注解大致意思为:如果不想进行优化,建议使用proguard-android.txt配置文件,另外,优化会存在风险,不能保证在所有版本的Dalvik上都正常运行。

另外,上面没有-dontoptimize项,也就是说它默认开启优化项,并且上面明确指明了优化相关的配置信息。

3、混淆结果

每次构建时 ProGuard 都会输出下列文件:
dump.txt 说明 APK 中所有类文件的内部结构。
mapping.txt 提供原始与混淆过的类、方法和字段名称之间的转换。
seeds.txt 列出未进行混淆的类和成员。
usage.txt 列出从 APK 移除的代码。

这些文件保存在 <module-name>/build/outputs/mapping/release/中。

4、解出混淆栈

混淆后的类、方法名等等难以阅读,拿到 crash 的堆栈信息后会发现很难定位,这时需要将混淆反解。

<sdk-root>/tools/proguard/bin路径下有附带的的反解工具,,Mac 或 Linux 系统为 proguardgui.sh,运行脚本

点击 ReTrace,选择该混淆包对应的 mapping 文件(混淆后在 <module-name>/build/outputs/mapping/release/ 路径下会生成 mapping.txt 文件,它的作用是提供混淆前后类、方法、类成员等的对照表),再将 crash 的 stack trace 黏贴进输入框中,点击右下角的 ReTrace ,混淆后的堆栈信息就显示出来了。
这里写图片描述
以上使用 GUI 程序进行操作,另一种方式是利用该路径下的 retrace 工具通过命令行进行反解,命令是

retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

参考文章:

ProGuard manual
写给 Android 开发者的混淆使用手册
Android进阶之ProGuard代码混淆
Android安全攻防战,反编译与混淆技术完全解析(下)

欢迎关注微信公众号:DroidMind
精品内容独家发布平台


呈现与博客不一样的技术干货

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值