引言
对于Android应用的混淆,网上有很多的资料,也有很多的相关案例和模板,相信大家也都比较熟悉。但是,对于一些公司要求混淆度比较高的,有的人就会比较犯难,因为网上的大多模块,并不能完成这个需求,那我们怎么能去最大程度上的给反编译者添加阅读难度呢,本文主要讲的是该方向的讲解。(本文不考虑加固这种方法,只是从混淆的角度来说,而且很简单,大家看完以后会豁然开朗的)
通过map实现自己的混淆需求
1.首先配置自定义混淆map文件,并配置到proguard-rules.pro文件中
首先创建一个 mapping.map 文件,然后在 proguard-rules.pro 文件中添加
-applymapping mapping.map 这句话。
1530873026(1).jpg
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.**
作者:AFinalDream
链接:https://www.jianshu.com/p/a1c7d0d5f194