android 混淆规则作用,Android混淆规则

简介

Java代码是非常容易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。

ProGuard是一个混淆代码的开源项目。它的主要作用就是混淆,当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。

官网地址:http://proguard.sourceforge.net/

原理

Java 是一种跨平台的、解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中。由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆。

混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后 jar 文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的。

Android 混淆

Android 混淆代码直接在Android Studio 中配置

android {

buildTypes {

release {

shrinkResources true

minifyEnabled true

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

}

}

由于混淆会增加编译时间,并且debug时编译器无法定位到具体位置,所以debug环境下不建议打开。

代码混淆

配置如 minifyEnabled true。

代码混淆包括四个步骤,代码压缩,优化,混淆,预校验。

压缩(shrink) : 移除无效的类,类成员,方法,属性等。

优化(optimize) : 分析和优化二进制代码,根据proguard-android-optimize.txt中的描述,优化可能会造成一定的风险,不能保证在所有版本的Dalvik上正常运行。因此android项目建议关闭该项。

混淆(obfuscate) : 把类名,属性名, 方法名替换为简短且无意义的名称。

预校验(previrfy) : 添加预校验信息。 这个预校验是作用在java 平台的, Android 平台上不需要这项功能,去掉之后还可以加快混淆速度。因此android 项目关闭该项。

这四个流程默认是开启的, 我们需要在Android混淆配置文件中关闭代码优化,和预校验功能,即-dontoptimize, -dontpreverify. 当然proguard-android.txt中默认已经关闭这两项了。

ed135ddd5996

项目混淆工作流程图

资源混淆

配置如 shrinkResources true。

压缩资源将移除项目及依赖库中未被使用的资源,可以减少apk的大小,一般建议开启。

资源处理包括合并资源,移除资源两个流程。

Android Studio 打包时会自动进行merge资源,不受该参数控制。

移除资源,需要配置该参数。不过建议可以使用lint先自行过一遍。

java 混淆

如果要将输出的jar包进行混淆,可以用proguard工具进行操作。分为命令行式和图像界面工具。可以去网上下载或者 android sdk提供了一个图形化工具proguard,可以进行混淆。路径如下 /sdk/tools/proguard/lib/proguardgui.jar 双击打开即可。

在其中配置相关的混淆参数即可。

代码混淆规则

Android项目中配置如下proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 。 由android sdk 中提供的默认混淆规则proguard-android.txt 和 用户自定义的混淆规则proguard-rules.pro 两部分组成。

命令

作用

-keep

防止类和成员被移除或者被重命名

-keepnames

防止类和成员被重命名

-keepclassmembers

防止成员被移除或者被重命名

-keepclassmembersname

防止成员被重命名

-keepclasseswithmembers

防止拥有该成员的类和成员被移除或者被重命名

-keepclasseswithmembernames

防止拥有该成员的类和成员被重命名

类通配符 *

匹配任意长度字符,但不含包名分隔符(.)

类通配符 **

匹配任意长度字符,并且包含包名分隔符(.)

类extends

即可以指定类的基类

类implements

匹配实现了某接口的类

类$

内部类

成员(方法)通配符 *

匹配任意长度字符,但不含包名分隔符(.)

成员(方法)通配符 **

匹配任意长度字符,并且包含包名分隔符(.)

成员(方法)通配符 ***

匹配任意参数类型

成员(方法)通配符 ...

匹配任意长度的任意类型参数

成员(方法)通配符 <>

匹配方法名,eg.

常见混淆命令

# 代码混淆压缩比,在0~7之间,默认为5,一般不下需要修改

-optimizationpasses 5

# 混淆时不使用大小写混合,混淆后的类名为小写

# windows下的同学还是加入这个选项吧(windows大小写不敏感)

-dontusemixedcaseclassnames

# 指定不去忽略非公共的库的类

# 默认跳过,有些情况下编写的代码与类库中的类在同一个包下,并且持有包中内容的引用,此时就需要加入此条声明

-dontskipnonpubliclibraryclasses

# 指定不去忽略非公共的库的类的成员

-dontskipnonpubliclibraryclassmembers

# 不做预检验,preverify是proguard的四个步骤之一

# Android不需要preverify,去掉这一步可以加快混淆速度

-dontpreverify

# 有了verbose这句话,混淆后就会生成映射文件

# 包含有类名->混淆后类名的映射关系

# 然后使用printmapping指定映射文件的名称

-verbose

-printmapping priguardMapping.txt

# 指定混淆时采用的算法,后面的参数是一个过滤器

# 这个过滤器是谷歌推荐的算法,一般不改变

-optimizations !code/simplification/artithmetic,!field/*,!class/merging/*

# 保护代码中的Annotation不被混淆

# 这在JSON实体映射时非常重要,比如fastJson

-keepattributes *Annotation*

# 避免混淆泛型

# 这在JSON实体映射时非常重要,比如fastJson

-keepattributes Signature

# 抛出异常时保留代码行号

-keepattributes SourceFile,LineNumberTable

keep 元素不进行混淆规则

# 保留所有的本地native方法不被混淆

-keepclasseswithmembernames class * {

native ;

}

# 保留了继承自Activity、Application这些类的子类

# 因为这些子类有可能被外部调用

# 比如第一行就保证了所有Activity的子类不要被混淆

-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.BackupAgentHelper

-keep public class * extends android.preference.Preference

-keep public class * extends android.view.View

-keep public class com.android.vending.licensing.ILicensingService

# 如果有引用android-support-v4.jar包,可以添加下面这行

-keep public class com.null.test.ui.fragment.** {*;}

# 保留Activity中的方法参数是view的方法,

# 从而我们在layout里面编写onClick就不会影响

-keepclassmembers class * extends android.app.Activity {

public void * (android.view.View);

}

# 枚举类不能被混淆

-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}

# 保留自定义控件(继承自View)不能被混淆

-keep public class * extends android.view.View {

public (android.content.Context);

public (android.content.Context, android.util.AttributeSet);

public (android.content.Context, android.util.AttributeSet, int);

public void set*(***);

*** get* ();

}

# 保留Parcelable序列化的类不能被混淆

-keep class * implements android.os.Parcelable{

public static final android.os.Parcelable$Creator *;

}

# 保留Serializable 序列化的类不被混淆

-keepclassmembers class * implements java.io.Serializable {

static final long serialVersionUID;

private static final java.io.ObjectStreamField[] serialPersistentFields;

!static !transient ;

private void writeObject(java.io.ObjectOutputStream);

private void readObject(java.io.ObjectInputStream);

java.lang.Object writeReplace();

java.lang.Object readResolve();

}

# 对R文件下的所有类及其方法,都不能被混淆

-keepclassmembers class **.R$* {

*;

}

# 对于带有回调函数onXXEvent的,不能混淆

-keepclassmembers class * {

void *(**On*Event);

}

其他自定义混淆规则

#内部类

-keep class com.null.test.MainActivity$* {

*;

}

#webview

-keepclassmembers class * extends android.webkit.WebViewClient {

public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);

public boolean *(android.webkit.WebView, java.lang.String);

}

-keepclassmembers class * extends android.webkit.WebViewClient {

public void *(android.webkit.WebView, java.lang.String);

}

#第三方库

-libraryjars ./libs/android-support-v4.jar

-dontwarn android.support.v4.**

-dontwarn **CompatHoneycomb

-dontwarn **CompatHoneycombMR2

-dontwarn **CompatCreatorHoneycombMR2

-keep interface android.support.v4.app.** { *; }

-keep class android.support.v4.** { *; }

-keep public class * extends android.support.v4.**

-keep public class * extends android.app.Fragment

资源保持规则

用shrinkResources true开启资源压缩后,所有未被使用的资源默认被移除。假如你需要定义哪些资源必须被保留,在 res/raw/ 路径下创建一个 xml 文件,例如 keep.xml。

通过一些属性的设置可以实现定义资源保持的需求,可配置的属性有:

tools:keep 定义哪些资源需要被保留(资源之间用“,”隔开)

tools:discard 定义哪些资源需要被移除(资源之间用“,”隔开)

tools:shrinkMode 开启严格模式

mapping文件

混淆过的包必须进行检查,避免因混淆引入的bug。

混淆后会在 路径/build/outputs/mapping/release/ 目录下会输出以下文件:

dump.txt 描述apk文件中所有类的内部结构

mapping.txt 提供混淆前后类,方法,类成员等的对照表

seeds.txt 列出没有被混淆的类和成员

usage.txt 列出被移除的代码

一般发布包的时候都要保留mapping.txt 文件。 目的有有两个, 1. 当出现线上crash时候,可以根据该mapping文件对照源码找到对应的位置。2. 当发布补丁包时候,也会指定该mapping文件,已避免补丁包无法使用。

解出混淆栈

在sdk/tools/proguard路径下附带了反解工具proguardgui.sh 或者 proguardgui.jar.打开即可,看到左侧的retrace, 选择混淆包对应的mapping.txt 文件, 再将crash 的 stack trace 粘贴到输入框中, 点击retrace 混淆前的堆栈信息即可显示。

命令行操作为:

retrace.bat|retrace.sh [-verbose] mapping.txt []

eg. retace.sh -verbose mapping.txt log.txt

指定mapping文件

增加proguard-path-rules.pro , 在其中指定-applymapping mapping.txt.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值