android confusion minifyEnabled

Obfuscated code (Obfuscated code), also known as flowery instructions, is the behavior of converting the code of a computer program into a functionally equivalent but difficult to read and understand form.

Why add code confusion
--------------------- I don't want to open source applications, in order to increase the cost of decompilation , but it can't completely prevent decompilation

Turn on obfuscation

as follows:

 

 release{
            minifyEnabled true//是否启动混淆 ture:打开   false:关闭
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

The role of the proguard-rules.pro file

  • gradleJust set it in the file of the project application directory minifyEnabled:true. Then we can proguard-rules.proadd our obfuscation rules to the file

what is proguard

  • Proguard is a tool that integrates file compression, optimization, obfuscation and verification functions
  • It detects and removes useless classes, variables, methods and properties
  • It optimizes bytecode and removes useless instructions.
  • It achieves the obfuscation effect by renaming class names, variable names and method names to meaningless names.
  • Finally it also validates the processed code

Common Configurations for Obfuscation

  • Proguard keywords
Proguard keywords describe
dontwarn dontwarn and keep can be said to be inseparable, especially when dealing with imported libraries.
keep Preserve classes and their members from obfuscation or removal
keepnames Retain the class and its members to prevent confusion, and the members will be removed if they are not referenced
keepclassmembers Only keep the members of the class to prevent confusion or removal
keepclassmembernames Only keep the members of the class to prevent confusion, members without references will be removed
keepclasseswithmembers Preserves classes and members of classes, prevents obfuscation or removal, retains specified members
keepclasseswithmembernames Retain classes and members in classes to prevent confusion, retain specified members, and members without references will be removed

Such as:
(1) Keep the classes and subpackages under a certain package

 

-keep public class com.droidyue.com.widget.**

(2) Keep the public method using otto in all classes

 

# Otto
-keepclassmembers class ** {
    @com.squareup.otto.Subscribe public *;
    @com.squareup.otto.Produce public *;
}

(3) Reserve the BOOK_NAME property of the Contants class

 

-keepclassmembers class com.example.admin.proguardsample.Constants {
     public static java.lang.String BOOK_NAME;
}

(4) dontwarn:
The imported library may have some references and other problems that cannot be found. Warnings may be issued during the build. If we do not deal with it, it will usually cause the build to abort. Therefore, in order to ensure that the build continues, we need to use dontwarn processing These are library warnings that we cannot resolve.

 

#比如关闭Twitter sdk的警告,我们可以这样做
-dontwarn com.twitter.sdk.**
  • Proguard wildcards
Proguard wildcards describe
<field> matches all fields in the class
<method> matches all methods in the class
<init> Matches all constructors in the class
* Matches characters of any length, excluding package name separators (.)
** Matches characters of any length, including package name separators (.)
*** matches any parameter type
... ...
  • basic rules

 

//不混淆某个类
-keep public class name.huihui.example.Test { *; }
//不混淆某个类的子类
-keep public class * extends name.huihui.example.Test { *; }
//不混淆所有类名中包含了“model”的类及其成员
-keep public class **.*model*.** {*;}
//不混淆某个接口的实现
-keep class * implements name.huihui.example.TestInterface { *; }
//不混淆某个类的构造方法
-keepclassmembers class name.huihui.example.Test { 
    public <init>(); 
}
//不混淆某个类的特定的方法
-keepclassmembers class name.huihui.example.Test { 
    public void test(java.lang.String); 
}
//不混淆某个类的内部类
-keep class name.huihui.example.Test$* {
        *;
 }
//两个常用的混淆命令,注意:
//一颗星表示只是保持该包下的类名,而子包下的类名还是会被混淆;
//两颗星表示把本包和所含子包下的类名都保持;
-keep class com.suchengkeji.android.ui.**
-keep class com.suchengkeji.android.ui.*
//用以上方法保持类后,你会发现类名虽然未混淆,但里面的具体方法和变量命名还是变了,
//如果既想保持类名,又想保持里面的内容不被混淆,我们就需要以下方法了
 
//不混淆某个包所有的类
-keep class com.suchengkeji.android.bean.** { *; }
//在此基础上,我们也可以使用Java的基本规则来保护特定类不被混淆,比如我们可以用extend,implement等这些Java规则。如下
# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
# 因为这些子类都有可能被外部调用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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

which should not be confused

  • If you use custom controls, make sure they don't participate in confusion
  • Enumeration is used to ensure that the enumeration is not confused
  • Do not obfuscate classes in third-party libraries
  • Classes that use reflection are not confused
  • Tools such as Gson are used to prevent the JavaBean class, that is, the entity class, from being confused
  • When citing a third-party library, the obfuscation rules of the library are generally marked. It is recommended to add the obfuscation rules when using it, so as not to find it at the end
  • Useful JS calls to WebView also need to ensure that the written interface methods are not confused, the reason is the same as the first one
  • Subclasses of Parcelable and Creator static member variables are not confused, otherwise Android.os.BadParcelableException will be generated
  • The four major components used, the custom Application* entity class
  • Classes called in JNI
  • View constructor (custom control), android:onClick, etc. used by Layout layout.

Come to a fool's confusion template

 

 
#
#-------------------------------------------基本不用动区域----------------------------------------------
#
#
# -----------------------------基本 -----------------------------
#
 
# 指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。)
-optimizationpasses 5
# 混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名)
-dontusemixedcaseclassnames
# 指定不去忽略非公共的库类(不跳过library中的非public的类)
-dontskipnonpubliclibraryclasses
# 指定不去忽略包可见的库类的成员
-dontskipnonpubliclibraryclassmembers
#不进行优化,建议使用此选项,
-dontoptimize
 # 不进行预校验,Android不需要,可加快混淆速度。
-dontpreverify
# 屏蔽警告
-ignorewarnings
# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保护代码中的Annotation不被混淆
-keepattributes *Annotation*
# 避免混淆泛型, 这在JSON实体映射时非常重要
-keepattributes Signature
# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
 #优化时允许访问并修改有修饰符的类和类的成员,这可以提高优化步骤的结果。
# 比如,当内联一个公共的getter方法时,这也可能需要外地公共访问。
# 虽然java二进制规范不需要这个,要不然有的虚拟机处理这些代码会有问题。当有优化和使用-repackageclasses时才适用。
#指示语:不能用这个指令处理库中的代码,因为有的类和类成员没有设计成public ,而在api中可能变成public
-allowaccessmodification
#当有优化和使用-repackageclasses时才适用。
-repackageclasses ''
 # 混淆时记录日志(打印混淆的详细信息)
 # 这句话能够使我们的项目混淆后产生映射文件
 # 包含有类名->混淆后类名的映射关系
-verbose
 
#
# ----------------------------- 默认保留 -----------------------------
#
#----------------------------------------------------
# 保持哪些类不被混淆
#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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 class android.support.** {*;}## 保留support下的所有类及其内部类
 
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
#表示不混淆上面声明的类,最后这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。
#----------------------------------------------------
 
# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
 
 
#表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致
-keepclasseswithmembernames class * {
    native <methods>;
}
 
 
#这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆
#表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性,
#当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}
 
#表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
 
#表示不混淆任何一个View中的setXxx()和getXxx()方法,
#因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。
-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);
}
 
#表示不混淆Parcelable实现类中的CREATOR字段,
#毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
# 这指定了继承Serizalizable的类的如下成员不被移除混淆
-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$* {
# *;
#}
#不混淆资源类下static的
-keepclassmembers class **.R$* {
    public static <fields>;
}
 
# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}
 
# 保留我们自定义控件(继承自View)不被混淆
-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);
}
 
#
#----------------------------- 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>;
}
 
#
#---------------------------------实体类---------------------------------
#--------(实体Model不能混淆,否则找不到对应的属性获取不到值)-----
#
-dontwarn com.suchengkeji.android.confusiondemo.md.**
#对含有反射类的处理
-keep class com.suchengkeji.android.confusiondemo.md.** { *; }
#
# ----------------------------- 其他的 -----------------------------
#
# 删除代码中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.**
 
 
#
# ----------------------------- 第三方 -----------------------------
#
-dontwarn com.orhanobut.logger.**
-keep class com.orhanobut.logger.**{*;}
-keep interface com.orhanobut.logger.**{*;}
 
-dontwarn com.google.gson.**
-keep class com.google.gson.**{*;}
-keep interface com.google.gson.**{*;}
#        。。。。。。

Let's take a look at the difference between confusing and not confusing (take this demo as an example)

Before obfuscation:


The directory in the above figure is very clear. The bean (md) has only Personone Activityand one ListView Adapter for the two entity classes:ListAdapter

As can be clearly seen from the figure above, for the obfuscated code, you can clearly see the structure and methods in the code, and it is easy to get the source code after decompilation. Look at the obfuscated
directory:

 


It can be seen from the obfuscated directory that the code is obviously different from the unobfuscated one. The attribute methods are basically represented by ah, b, c..., and it is even more difficult to understand the code results and methods, which reduces the externality of the source code. leak etc.

Note:
Someone may want to ask why there is a Datas entity class in the md (bean) file in my project. Why the directory is not seen after confusion, because the removal of useless resource files is enabled in the confusion configuration, so it is not referenced. In the case of this resource, the resource will be automatically deleted when packaging.
Adding confusion to the application is not to open source applications. In order to increase the cost of decompilation, it cannot completely prevent decompilation.

Proguard will output when building: dump.txt (describes the internal structure of all class files in the APK), mapping.txt (provides conversion between original and obfuscated classes, methods and field names), seeds.txt (lists unspecified Obfuscated classes and members), usage.txt (lists the code removed from the APK), the output path is:F:\...\ConfusionDemo\app\build\outputs\mapping


Reprint address: https://www.jianshu.com/p/b5b2a5dfaaf4

Guess you like

Origin blog.csdn.net/xiaowang_lj/article/details/131299481