Android 混淆机制基础

混淆,将类名、方法名、成员变量等重命名为无意义的简短名称,以增加逆向工程的难度,同时通过移除无用的类减少包的大小。

proguard-android.txt:sdk 默认的混淆配置
proguard-rules.pro:针对本模块做出的特殊混淆处理

混淆基础语法

混淆语法主要用于定义不需要混淆的代码。

混淆的语法有很多,下面列出常用语法及使用说明:

  • 不混淆指定类
-keep class com.xx.Test{*;}
  • 不混淆指定路径下的所有类/接口
-keep class com.xx.model.** { *; }
  • 不混淆某个类的特定函数
-keepclassmembers class com.xx.Test{
    public void 函数名(java.lang.String);
}

对于构造函数:

-keepcalssmembers clsss com.xx.Test{
    public <init>(java.lang.String)
}
  • 不混淆某个类/接口的子类/实现
-keep public class * extend com.xx.Test

-keep class * implements com.xx.Test {
  public static final com.xx.Test$Creator *;
}
  • 如果项目混淆,则会在 build/outputs/mapping/xx 目录下生成以下几个文件:

mapping.txt:混淆前后的映射关系;

seeds.txt:未混淆的类及成员;

usage.txt:从 apk 中删除的代码;(混淆会优化代码,将一些不使用的类删除)

dump.txt:所有 class 的内部结构。

利用 mapping.txt,收到异常报告时,可以定位问题来源,但需要注意的是每次混淆打包都会覆盖之前的 mapping.txt

  • 其它(选配)
-ignorewarnings # 忽略警告,避免打包时某些警告出现
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames  # 不使用大小写混合类名
-dontskipnonpubliclibraryclasses # 不混淆第三方 jar 中的非 public classes
-dontskipnonpubliclibraryclassmembers #不混淆第三方 jar 的非 public class
-dontpreverify   # 混淆时不做预校验
-dontshrink # 禁止删除无用包
-dontoptimize # 不启用优化、合并代码
-verbose    # 混淆时记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
-renamesourcefileattribute SourceFile 

更多可配置选项可查询 Android 代码混淆选项详细说明

混淆注意事项

因为混淆会重新命名类名、方法名、变量名,当某些代码要求原名调用时,混淆后的代码因为类名找不到会导致 crash。以下情况不能/不建议混淆(可作为基本混淆规则配置在混淆文件中,多余的配置不会导致编译失败):

1.反射中使用的类或变量;

2.bean 对象;

3.四大组件;(四大组件需要在 AndroidManifest 注册)

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.support.v4.app.FragmentActivity
-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
-dontnote com.android.vending.licensing.ILicensingService

4.注解;(用于运行时、编译时反射)

-keepattributes *Annotation*

5.枚举;

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

6.JNI 调用 Java 方法;

7.Java 调用 Native 方法;

-keepclasseswithmembernames class * {
    native <methods>;
}

8.JS 调用 Java 方法;

-keepattributes *JavascriptInterface*

9.WebView 中 JavaScript 的调用方法不能混淆;

-keepclassmembers class fqcn.of.javascript.interface.for.Webview {
    pub1ic *;
}

-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);
}

10.第三方库使用其自身混淆规则,或干脆一律不混淆;

-dontwarn com.xx.xx.**
-keep class com.xx.xx.** { *;}

11.Parcelable 序列化相关类;

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-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();
}

12.Gson;

-keep class com.google.gson.** { *; }
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.** {
    <fields>;
    <methods>;
}
-dontwarn com.google.gson.**

部分内容参考自《 Android 组件化架构》一书,并查缺补漏。

转载于:https://www.jianshu.com/p/266774a713c0

猜你喜欢

转载自blog.csdn.net/weixin_34257076/article/details/91220508