Android代码混淆

简介: Android代码混淆

代码混淆的作用

  1.令 APK 难以被逆向工程,即很大程度上增加反编译的成本;
  2.在打包时移除无用资源,显著减少 APK 体积;
  3.对字节码进行优化,移除无用指令,应用运行更快;
  4.以变通方式避免 Android 中常见的 64k 方法数引用的限制。

设置混淆

1. 在模块目录下的 build.gradle 文件中配置以下代码

  buildTypes {
        release {
            minifyEnabled true // 开启混淆
            shrinkResources true // 优化无用资源
        }
    }

2. 在 proguard-rules.pro 文件中添加混淆规则

通用混淆规则

-optimizationpasses 5                       # 代码混淆的压缩比例,值介于0-7,默认5
-verbose                                    # 混淆时记录日志
-dontoptimize                               # 不优化输入的类文件
-dontshrink                                 # 关闭压缩
-dontpreverify                              # 关闭预校验(作用于Java平台,Android不需要,去掉可加快混淆)
-dontoptimize                               # 关闭代码优化
-dontobfuscate                              # 关闭混淆
-ignorewarnings                             # 忽略警告
-dontwarn com.squareup.okhttp.**            # 指定类不输出警告信息
-dontusemixedcaseclassnames                 # 混淆后类型都为小写
-dontskipnonpubliclibraryclasses            # 不跳过非公共的库的类
-printmapping mapping.txt                   # 生成原类名与混淆后类名的映射文件mapping.txt
-useuniqueclassmembernames                  # 把混淆类中的方法名也混淆
-allowaccessmodification                    # 优化时允许访问并修改有修饰符的类及类的成员
-renamesourcefileattribute SourceFile       # 将源码中有意义的类名转换成SourceFile,用于混淆具体崩溃代码
-keepattributes SourceFile,LineNumberTable  # 保留行号
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod # 避免混淆注解、内部类、泛型、匿名类
-optimizations !code/simplification/cast,!field/ ,!class/merging/   # 指定混淆时采用的算法

常用匹配符

  # * 星号
  匹配指定包下的类或者类的子类:
    -keep class top.gaojc.model.*
    -keep class top.gaojc.model.**
  # 释义:
  1. 一个*号表示只保持该包(top.gaojc.model)下的类名不被混淆,而子包下的类名还是会混淆,比如model下面有个bean子包,它里面的类会被混淆
  2. 两个*号表示保持该包(top.gaojc.model)下及该包下子包的包名不被混淆
  3. 如果既想保持类名,又想保持方法和成员变量不被混淆,需要使用以下方式:
    -keep class top.gaojc.model.*{*;}
  
  <init> 匹配类中所有构造函数

  <methods> 匹配类、接口中所有方法

  <fileds> 匹配类、接口中所有字段

常用命令

# 保留类和类成员,防止类和类成员被移除或被混淆;
-keep

# 保留类和类成员,防止被混淆,但没有被引用的类成员会被移除
-keepnames

# 只保留类成员,防止类成员被移除或被混淆;
-keepclassmembers

# 只保留类成员,防止被混淆,但没有被引用的成员会被移除
-keepclassmembernames

# 保留类和类成员,防止被混淆或移除,如果指定的类成员不存在还是会被混淆
-keepclasseswithmembers

# 保留类和类成员,防止被混淆,如果指定的类成员不存在还是会被混淆,没有被引用的类成员会被移除
-keepclasseswithmembernames     

# 不混淆某个类的类名及类中的内容
-keep class top.gaojc.gameapp.debug.DebugActivity { *; }

# 不混淆指定包名下的类名,不包括子包下的类名
-keep class top.gaojc.gameapp*

# 不混淆指定包名下的类名,及类里的内容
-keep class top.gaojc.gameapp* {*;}

# 不混淆指定包名下的类名,包括子包下的类名
-keep class top.gaojc.gameapp**

# 不混淆某个类的子类
-keep public class * extends top.gaojc.gameapp.base.BaseActivity

# 不混淆实现了某个接口的类
-keep class * implements top.gaojc.gameapp.dao.ChatDaiImpl

# 不混淆类名中包含了"entity"的类,及类中内容
-keep class **.*entity*.** {*;}

# 不混淆内部类中的所有public内容
-keep class top.gaojc.gameapp.view.CustomView$OnClickInterface {
    public *;
}

# 不混淆指定类的所有方法
-keep top.gaojc.gameapp.debug.DebugActivity {
    public <methods>;
}

# 不混淆指定类的所有字段
-keep top.gaojc.gameapp.debug.DebugActivity {
    public <fields>;
}

# 不混淆指定类的所有构造方法
-keep top.gaojc.gameapp.debug.DebugActivity {
    public <init>;
}

# 不混淆指定参数作为形参的方法
-keep top.gaojc.gameapp.debug.DebugActivity {
    public <methods>(java.lang.String);
}

# 不混淆类的特定方法
-keep top.gaojc.gameapp.debug.DebugActivity {
    public test(java.lang.String);
}

# 不混淆native方法
-keepclasseswithmembernames class * {
    native <methods>;
}

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

#不混淆资源类
-keepclassmembers class **.R$* {
    public static <fields>;
}

# 不混淆自定义控件
-keep public class * entends android.view.View {
    *** get*();
    void set*(***);
    public <init>;
}

# 不混淆实现了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();
}

# 不混淆实现了parcelable接口的类成员
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}
# 保留

注意事项

  -. jni方法不可混淆,方法名需与native方法保持一致
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
  -. 反射用到的类不混淆,否则反射可能出问题
  
  -. 四大组件、Application子类、Framework层下的类、自定义的View默认不会被混淆,无需另外配置
  
  -. WebView的JS调用接口方法不可混淆
  
  -. 注解相关的类不混淆
  
  -. GSON、Fastjson等解析的Bean数据类不可混淆
  
  -. 与服务端交互解析成的实体对象不能设置混淆,否则不能解析出正确的对象
    -keep class top.gaojc.model.bean.*{*;} # 自定义数据模型的bean目录
    
  -. 枚举enum类中的values和valuesof这两个方法不可混淆(反射调用)
  
  -. 继承Parceable和Serializable等可序列化的类不可混淆
  
  -. 第三方库或SDK,请参考第三方提供的混淆规则,没提供的话,建议第三方包全部不混淆

如何查看是否已混淆

在 Android Studio 的 Build 菜单下点击 Analyze APK 选项,选择生成的apk包,然后点击 classes.dex 文件即可看到混淆后的代码结构

目录
相关文章
|
算法 Java Android开发
补齐Android技能树 - 从害怕到玩转Android代码混淆(下)
本节稍微深入点探索下Android中的代码混淆~
316 0
|
6天前
|
安全 Android开发 数据安全/隐私保护
代码安全之代码混淆及加固(Android)
代码安全之代码混淆及加固(Android)
53 0
|
6天前
|
安全 Java Android开发
Android App开发之安全加固中反编译、代码混淆、第三方加固以及重签名的讲解及实战(图文解释 简单易懂)
Android App开发之安全加固中反编译、代码混淆、第三方加固以及重签名的讲解及实战(图文解释 简单易懂)
80 0
|
存储 XML Java
补齐Android技能树 - 从害怕到玩转Android代码混淆(中)
本节稍微深入点探索下Android中的代码混淆~
571 0
|
开发工具 Android开发 Kotlin
补齐Android技能树 - 从害怕到玩转Android代码混淆(上)
本节稍微深入点探索下Android中的代码混淆~
291 0
|
Android开发
Android studio--代码混淆
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/79003860          混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。
1434 0