您的位置:首页 > 移动开发 > Android开发

android用proGuard代码混淆

2018-01-19 10:43 267 查看

简介

因为java是一门跨平台语言,java虚拟机会把java源代码编译成.class文件,从而各种软件可对.class文件进行反编译,造成代码不安全,以至于android引入了proGuard对.class文件进行混淆。

目录

proguard是什么?

proguard技术的功能

proguard工作原理

proguard在android中的运用

proguard是什么?

proguard工具是用于压缩,优化,混淆我们.class文件的代码,主要作用是可以将代码中的无用类,字段,方法和属性同时进行混淆

proguard技术功能

压缩(Shrink):检测并移除代码中的无用的类,字段,方法和属性。

优化(Optimize):对字节码进行优化,移除无用的指令。

混淆(Obfuscate):对于一些无意义的名称(a,b,c),对类,字段和方法进行重命名。

预检(Preveirfy):在Java平台上对处理后的代码进行预检,确保加载的class文件是可执行的。

总结:Proguard是一个Java类文件压缩器、优化器、混淆器、预校验器。这些步骤让代码更精简,更高效,也更难被逆向(破解)。

proguard工作原理



ProGuard是由shrink->optimize->obfuscate->preverify几个步骤组成的,每个步骤可以独立开来的,我们可用脚本来决定执行其中的哪几个步骤。

ProGuard又是怎么知道这个代码没有被用到呢?

这里引入一个Entry Point的概念,Entry Point是在ProGuard过程中不会被处理的类或方法。在压缩的步骤中,ProGuard会从上述的Entry Point开始递归遍历,搜索哪些类和类的成员在使用,对于没有被使用的类和类的成员,就会在压缩段丢弃,在接下来的优化过程中,那些非Entry Point的类、方法都会被设置为private、static或final,不使用的参数会被移除,此外,有些方法会被标记为内联的,在混淆的步骤中,ProGuard会对非Entry Point的类和方法进行重命名。

proguard在android中的运用

我们可以从三个步骤进行混淆:

1.基本混淆

2.针对AppModule进行混淆

3.针对第三方进行混淆

1.基本混淆

android sdk 的 /sdk/tools/proguard/proguard-android.txt 中已经提供了基本的混淆配置,不需要在 proguard-rules.pro 中重复配置。

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

# 不混淆注解(注解不能被混淆)
-keepattributes *Annotation*
# 不混淆指定类
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native # 不混淆native的方法
-keepclasseswithmembernames class * {
native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans # 不混淆继承View的所有类的set和get方法
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
# 不混淆继承Activity的所有类的中的参数类型为View的方法
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations # 不混淆枚举类型的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类中所有static字段
-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.**

# Understand the @Keep support annotation.
# 不混淆指定的类及其类成员
-keep class android.support.annotation.Keep

# 不混淆使用注解的类及其类成员
-keep @android.support.annotation.Keep class * {*;}

# 不混淆所有类及其类成员中的使用注解的方法
-keepclasseswithmembers class * {
@android.support.annotation.Keep <methods>;
}

# 不混淆所有类及其类成员中的使用注解的字段
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}

# 不混淆所有类及其类成员中的使用注解的初始化方法
-keepclasseswithmembers class * {
@android.support.annotation.Keep <init>(...);
}


针对Appmodule进行混淆,可在proguard-rule.pro进行常用的配置

#指定代码的压缩级别
-optimizationpasses 5

# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#记录生成的日志数据,gradle build时在本项目根目录输出
#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt

#移除log代码
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** i(...);
public static *** d(...);
public static *** w(...);
public static *** e(...);
}

#不混淆反射用到的类
-keepattributes Signature
-keepattributes EnclosingMethod

#保持继承自系统类的class不被混淆
-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 interface android.support.v4.app.** { *; }
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep interface android.support.v7.app.** { *; }
-keep class android.support.v7.** { *; }
-keep public class * extends android.support.v7.**
-keep public class * extends android.app.Fragment
-keep class * extends android.**{*;}

#不混淆Serializable接口的子类中指定的某些成员变量和方法
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

############ 不混淆引用的jar ############

#不混淆butterknife
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
-dontwarn butterknife.internal.**

############ 保持自定义控件不被混淆 ############
-keepclasseswithmembernames class * {
public <init>(android.content.Context);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int, int);
}

#不混淆整个包
#-keep class com.test.test.**{*;}

#不混淆对外接口的public类名和成员名,否则外部无法调用
#-keep public interface com.test.test.**{*;}
#-keep public enum com.test.test.**{*;}
#-keep public class com.test.test.**{
#    public *;
#}

# 对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)
}
# 保留JS方法不被混淆
-keepclassmembers class com.example.xxx.MainActivity$JSInterface1 {
<methods>;
}
#
对于第三方包进行混淆,一般都在各自的文档有表明,在这里只需要复制即可
# 对alipay的混淆处理
-libraryjars libs/alipaysdk.jar
-dontwarn com.alipay.android.app.**
-keep public class com.alipay.**  { *; }


总结:

以上就是android对于代码混淆的过程,我们的测试工作也要基于混淆包进行,这样才能尽早发现问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: