ProGuard Code Confusion

Posted by ditusade on Wed, 15 May 2019 00:39:36 +0200

Proguard is a Java class file compressor, optimizer, obfuscator, pre-verifier. Compression links detect and remove unused classes, fields, methods, and attributes. Optimization links analyze and optimize byte codes for methods. Confusion links rename classes, variables, and methods with meaningless short variables. These steps make the code simpler, more efficient, and harder to reverse.

How to write a ProGuard configuration file

1. Basic confusion

Confusion file basic configuration information, any APP should use, can be used as a template.

(1) Basic commands

#Code confusion compression ratio, between 0 and 7, defaults to 5, generally does not need to be changed
-optimizationpasses 5

#Do not use case mixing when confusing. The confused class name is lowercase
-dontusemixedcaseclassnames

#Specify classes that do not ignore non-public Libraries
-dontskipnonpubliclibraryclassmembers

#Without pre-testing, preverify is one of the four steps of proguard
#Android does not require preverify, and removing this step will speed up confusion
-dontpreverify

#With verbose, confusion produces a mapping file
#Mapping relationships containing class names - > confused class names
#Then use printmapping to specify the name of the mapping file
-verbose
-printmapping proguardMapping.txt

#Specify the algorithm to use for confusion, followed by a filter
#This filter is Google's recommended algorithm and generally does not change
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#Protect the Annotation in your code from confusion.
-keepattributes *Annotation*

#Avoid confusing generics
-keepattributes Signature

#Keep the line number of the code when throwing an exception, which is easy to locate in exception analysis
-keepattributes SourceFile,LineNumberTable

#Do not skip over non-public classes, which are skipped by default
-dontskipnonpubliclibraryclasses

#This is for the windows operating system, because ProGuard assumes that the operating system used is able to distinguish between two file names that are only case-sensitive
#But windows is not such an operating system
-dontusemixedcaseclassnames

(2). Things to keep

#Keep all local native methods unambiguous
-keepclasseswithmembernames class * {
    native <methods>;
}

#Keep subclasses inherited from Activity, Application These classes
#Because of these subclasses, they are all likely to be called externally
#For example, the first line ensures that all activities'subclasses are not confused
-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.ContentProvier
-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 * extends com.android.vending.licensing.ILicensingService

#If you have references to the android-supoort-v4.jar package, you can add the following line
-keep public class com.xxxx.app.ui.fragment.** {*;}

#The method parameter that remains in the Activity is the method of view.
#So we write onClick s in layout without affecting them
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

#Enumeration classes cannot be confused
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#Keep custom controls (inherited from View) unambiguous
-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);
}

#Keep Parcelable serialized classes unambiguous
-keep class * implements android.os.Parcelable{
    public static final android.os.Parcelable$Creator *;
}

#Classes that retain Serializable serialization cannot be confused
-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();
}

#All classes and their methods under R (Resources) should not be confused
-keep class **.R$* {
    *;
}

#For onXXEvent with callback function, it should not be confused
-keepclassmembers class * {
    void *(**On*Event);
}

2. Customize for App

(1) Retain entity classes and members without confusion

For entity classes, keep their set and get methods; for boolean get methods, some people like to name isXXX, so don't omit

# Keep entity classes and members unambiguous
-keep public class com.xxxx.entity.** {
    public void set*(***);
    public *** get*();
    public *** is*();
}

(2) Embedded classes

# Keep embedded classes unobfuscated
-keep class com.example.xxx.MainActivity$* { *; }

This $sign is the symbol used to split an embedded class from its parent.

(3) Processing of WebView

# Processing of WebView
-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)
}

(4) For javascript processing

# Keep JS methods unambiguous
-keepclassmembers class com.example.xxx.MainActivity$JSInterface1 {
    <methods>;
}

(5) Processing reflection

    Class.forName("SomeClass")
    SomeClass.class
    SomeClass.class.getField("someField")
    SomeClass.class.getDeclaredField("someField")
    SomeClass.class.getMethod("someMethod", new Class[] {})
    SomeClass.class.getMethod("someMethod", new Class[] { A.class })
    SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
    SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
    SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
    SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
    AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
    AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
    AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")

When confusing, search for the above methods in your project and keep the names of the corresponding classes or methods unambiguous.

(6) Solutions for Custom view

However, any custom view of the XML layout file configuration in the Layout directory should not be confused.

3. Solutions for third-party jar packages

Generally speaking, these SDKs are confused by ProGuard, and all we need to do is avoid confusing the classes and methods of these SDKs in our APP.

(1). For android-support-v4.jar

# Solutions for android-support-v4.jar
-libraryjars libs/android-support-v4.jar
-dontwarn android.support.v4.**
-keep class android.support.v4.**  { *; }
-keep interface android.support.v4.app.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment

(2) Solutions for other third-party jar packages

This depends on the obfuscation strategy of third-party packages, which typically have explanatory text about obfuscation in their sdk s, such as:

 Confusion handling for alipay
-libraryjars libs/alipaysdk.jar
-dontwarn com.alipay.android.app.**
-keep public class com.alipay.**  { *; }

 

Topics: Android Java Windows Fragment