2022

Android代码混淆

2018-12-31  本文已影响0人  Thor_果冻

代码混淆

如有错误可以QQ邮箱联系,745661590@qq.com
github不支持脚注

代码混淆概念[1]

代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。目前已经存在许多种功能各异的代码混淆器。

混淆配置

我们一般直接在app的build.gradle文件中设置minifyEnabled true即可;
我们一般也加上shrinkResources true,打开资源压缩。用shrinkResources true开启资源压缩后,所有未被使用的资源默认被移除。

android {
    buildTypes {
        release {
            minifyEnabled true//是否启动混淆true:打开;false:关闭
            shrinkResources true//打开资源压缩。
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

设置白名单

白名单也就是proguard-rules.pro中我们自定义哪些不添加混淆。

关键字[2]

关键字 描述
dontwarn dontwarn是一个和keep可以说是形影不离,尤其是处理引入的library时.
keep 保留类和类中的成员,防止被混淆或移除
keepnames 保留类和类中的成员,防止被混淆,成员没有被引用会被移除
keepclassmembers 只保留类中的成员,防止被混淆或移除
keepclassmembernames 只保留类中的成员,防止被混淆,成员没有引用会被移除
keepclasseswithmembers 保留类和类中的成员,防止被混淆或移除,保留指明的成员
keepclasseswithmembernames 保留类和类中的成员,防止被混淆,保留指明的成员,成员没有引用会被移除
[保持命令] [类] {
    [成员] 
}

通配符

去除反斜杠,markDown中我不知道怎么去除

通配符 描述
* 匹配任意长度字符,不包含包名分隔符(.)
** 匹配任意长度字符,包含包名分隔符(.)
*** 匹配任意参数类型
$ 内部类
<\init> 匹配类中所有的构造函数
<\fields> 匹配类中的所有字段
<\method> 匹配类中所有的方法
匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。
extends 即可以指定类的基类
implement 匹配实现了某接口的类

规则使用

我总结的

最新的proguard-android.txt中添加了很多下面已经有的,再添加的时候看看是不是已经有了


#######################-----app中-----############################
#如果使用了Gson之类的工具要使被它解析的JavaBean类即实体类不被混淆

#######################-----第三方-----############################

#######################-----WebView(项目中没有可以忽略)-----############################
#webView需要进行特殊处理
-keepclassmembers class fqcn.of.javascript.interface.for.Webview {
   public *;
}
-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, jav.lang.String);
}
#在app中与HTML5的JavaScript的交互进行特殊处理
#我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理:
-keepclassmembers class com.ljd.example.JSInterface {
    <methods>;
}


#######################-----其他-----############################
# 删除代码中Log相关的代码
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
}

# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**

#######################-----基本-----############################
#指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。)
-optimizationpasses 5

#混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名,混淆后类名都为小写)
-dontusemixedcaseclassnames

#指定不去忽略非公共的库的类
#默认跳过,有些情况下编写的代码与类库中的类在同一个包下,并且持有包中内容的引用,此时就需要加入此条声明
-dontskipnonpubliclibraryclasses
#指定不去忽略非公共的库的类的成员
-dontskipnonpubliclibraryclassmembers

#Optimization is turned off by default. Dex does not like code run
#hrough the ProGuard optimize and preverify steps (and performs some
#of these optimizations on its own).
#不进行优化,建议使用此选项,不优化输入的类文件(原因见上边的原英文注释)
-dontoptimize
#不做预检验,preverify是proguard的四个步骤之一
#Android不需要preverify,去掉这一步可以加快混淆速度
-dontpreverify

#屏蔽警告
-ignorewarnings

#指定混淆是采用的算法,后面的参数是一个过滤器
#这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#避免混淆Annotation、内部类、泛型、匿名类
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod

#表示不混淆声明的两个类,这两个类我们基本也用不上,是接入Google原生的一些服务时使用的
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

#抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
#重命名抛出异常时的文件名称,点击鼠标可以到达错误文件位置
-renamesourcefileattribute SourceFile

#混淆时是否记录日志
-verbose

#不混淆R文件中的所有静态字段,以保证正确找到每个资源的id
-keepclassmembers class **.R$* {
    public static <fields>;
}
 
#保留四大组件,自定义的Application等这些类不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-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

#处理support包
-keep class android.support.** {*;}
-dontnote android.support.**
-dontwarn android.support.**

#保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

#保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

#保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

#保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

#see http://proguard.sourceforge.net/manual/examples.html#beans
#不混淆View中的setXxx()和getXxx()方法,以保证属性动画正常工作
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

#不混淆Activity中参数是View的方法,例如,一个控件通过android:onClick="clickMethodName"绑定点击事件,混淆后会导致点击事件失效
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

#保留Keep注解的类名和方法(最新的proguard-android.txt中包括了这个)
-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>(...);
}

#第三方jar包不被混淆
-keep class com.github.** {*;}

参考文档


  1. 摘抄自百度百科-代码混淆

  2. 摘抄自Android混淆的关键字描述

上一篇下一篇

猜你喜欢

热点阅读