引言
对于Android应用的混淆,网上有很多的资料,也有很多的相关案例和模板,相信大家也都比较熟悉。但是,对于一些公司要求混淆度比较高的,有的人就会比较犯难,因为网上的大多模块,并不能完成这个需求,那我们怎么能去最大程度上的给反编译者添加阅读难度呢,本文主要讲的是该方向的讲解。(本文不考虑加固这种方法,只是从混淆的角度来说,而且很简单,大家看完以后会豁然开朗的)
通过map实现自己的混淆需求
1.首先配置自定义混淆map文件,并配置到proguard-rules.pro文件中
首先创建一个 mapping.map 文件,然后在 proguard-rules.pro 文件中添加
-applymapping mapping.map 这句话。
2.具体的混淆语句编写及要求
- 对类名进行混淆
com.xx.xx.xx -> com.a.a.a:
以上是对类名进行混淆的语句,com.xx.xx.xx 表示的是你需要混淆的类全路径, com.a.a.a表示的是你混淆后的别名。
注:配置的别名后的 “:” 冒号一定不能少。
- 对变量进行混淆
java.lang.String usrname-> a
( 八大基本数据类型以外的类型)以上是对变量进行混淆的语句,java.lang.String 表示的是你要混淆的变量的类型路径,usrname 表示的是你要混淆的变量名称, a 表示的是你混淆后的别名。
int number -> b
( 八大基本数据类型) 以上是对变量进行混淆的语句,int ** 表示的是你要混淆的变量的类型,number ** 表示的是你要混淆的变量名称, b 表示的是你混淆后的别名。
注:对变量的混淆,需要注意的有两点:
1.混淆语句必须一行写完,假设如果过长,分两行来写,那么该混淆语句不会被执行混淆
2.对于变量的类型定义,分基本数据类型和引用数据类型,他们混淆定义的区别在于写法:基本数据类型可以直接写该类型进行定义,而引用数据类型需要写该数据类型的全路径进行定义,否则,会混淆失败
- 对方法进行混淆
void push(android.app.Activity) -> a
以上是对方法进行混淆的语句,void ** 表示的是你要混淆的方法返回类型,push** 表示的是你要混淆的方法名称, android.app.Activity 表示的是你要混淆的方法参数,a 表示的是你混淆后的别名。
注:对方法的混淆,需要注意的有两点:
1.混淆语句必须一行写完,假设如果过长,分两行来写,那么该混淆语句不会被执行混淆。
2.返回参数、方法传入参数如果是引用类型,也需要写该类型的全路径。
混淆通用模板
以下内容是网上最多的基本混淆模板,我就不进行解说了。
#-------------------------------------------基本不用动区域--------------------------------------------
#---------------------------------基本指令区----------------------------------
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontskipnonpubliclibraryclasses # 指定不去忽略非公共的库类
-dontskipnonpubliclibraryclassmembers # 指定不去忽略包可见的库类的成员
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/* # 混淆时所采用的算法
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
#----------------------------------------------------------------------------
-ignorewarnings # 是否忽略检测,(是)
#---------------------------------默认保留区---------------------------------
-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
-keep class android.support.** {*;}
#-ignorewarnings -keep class * { public private *; }
#如果有引用v4包可以添加下面这行
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-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);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-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();
}
#表示不混淆R文件中的所有静态字段
-keep class **.R$* {
public static <fields>;
}
-keepclassmembers class * {
void *(**On*Event);
}
#----------------------------------------------------------------------------
#---------------------------------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);
}
一般以下情况都会不混淆:
1.使用了自定义控件那么要保证它们不参与混淆
2.使用了枚举要保证枚举不被混淆
3.对第三方库中的类不进行混淆
4.运用了反射的类也不进行混淆
5.使用了 Gson 之类的工具要使 JavaBean 类即实体类不被混淆
6.在引用第三方库的时候,一般会标明库的混淆规则的,建议在使用的时候就把混淆规则添加上去,免得到最后才去找
7.有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因和第一条一样
8.Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常
9.Android四大组件和Application最好也不要混淆
第三方库常用混淆
#---------------------------------2.第三方库---------------------------------
#okhttp3
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-keep class okhttp3.** { *;}
-keep class okio.** { *;}
-dontwarn sun.security.**
-keep class sun.security.** { *;}
-dontwarn okio.**
-dontwarn okhttp3.**
#retrofit2
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-dontwarn org.robovm.**
-keep class org.robovm.** { *; }
# RxJava RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
-dontnote rx.internal.util.PlatformDependent
# Retrofit, OkHttp, Gson
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**
-dontwarn rx.**
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepclasseswithmembers class * {
@retrofit.http.* <methods>;
}
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Rxjava-promises
-keep class com.darylteo.rx.** { *; }
-dontwarn com.darylteo.rx.**
# RxJava 0.21
-keep class rx.schedulers.Schedulers {
public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
public <methods>;
}
-keep class rx.schedulers.TestScheduler {
public <methods>;
}
-keep class rx.schedulers.Schedulers {
public static ** test();
}
#butterknife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
# RxLifeCycle2
-keep class com.trello.rxlifecycle2.** { *; }
-keep interface com.trello.rxlifecycle2.** { *; }
-dontwarn com.trello.rxlifecycle2.**
-keep class com.github.mikephil.charting.** { *; }
-dontwarn com.github.mikephil.charting.data.realm.**
福利
以下链接是个人觉得对混淆介绍比较有用的文章链接
http://www.imgeek.org/article/825308232
https://blog.csdn.net/double2hao/article/details/51277943
//www.greatytc.com/p/b471db6a01af
https://blog.csdn.net/bihansheng2010/article/details/51353023