Recently, the library of the company project needs to be released to the third party, so the problem of code security was exposed. Previously, it was handled by other Android teams inside, but the way to deal with it was very violent, which was to directly not confuse our library project, so that the code was easily decompiled. I had to force a wave.
This article records how to do android Libray project obfuscation experience. Android is definitely confused with ProGuard, so let’s get started.
1. ProGuard basis
1.1 Basic ProGuard Configuration
There are plenty of articles on obfuscation learning on the web, and HERE I’ve compiled some basic configuration options
# Specify the compression level of the code. The value is between 0 and 7. Optimizationpasses 5 # Print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes 5 # print obliquity passes To make decomcompiling more difficult, you can choose not to compress -dontshrink # Preserves the name and method of the argument. This option preserves debug-level properties. - keepParameterNames # Filters generics, enabling this only when conversion errors occur. The current project has no generic types for the time being, - KeepAttributes *Annotation* # specifies not to ignore members of classes that are not public libraries - dontskipnonpubliclibraryclassmembers # specify not to ignore the public library classes (don't jump the non public class library) - dontskipnonpubliclibraryclassesCopy the code
If there is an unreasonable or better option remember to tell me yo 😄 thank you very much
1.2 Proguard keywords about Keep
The keyword | describe |
---|---|
keep | Preserves classes and members of classes to prevent confusion or removal |
keepnames | Preserves classes and members of classes to prevent confusion, and members that are not referenced are removed |
keepclassmembers | Keep only members of the class to prevent confusion or removal |
keepclassmembernames | Only members of the class are retained to prevent confusion, and members without references are removed |
keepclasseswithmembers | Preserves classes and members of classes, preventing confusion or removal, and preserves specified members |
keepclasseswithmembernames | Retain classes and members of classes to prevent confusion, retain specified members, and remove members that do not have references |
The first keyword worth noting here is keep
If you want to keep the name of the class, you can configure it as follows:
# the following configuration only retained the MyClass class name, all the members of the class will still be confused - keep class. Com. Your class. The name. The MyClass # only specify your class members matching rules can make effective confusing rules inside the body. -keep class com.your.class.name.MyClass {*; } # for 🌰 the following configuration is that I used to handle class library project, expected to open out all public methods, do not want to be mixed configuration - keep class. Com. Your class. The name. MyClass {public < fields >; public <methods>; public static final <fields>; }Copy the code
1.3 Proguard Wildcard
The wildcard | describe |
---|---|
<field> |
Matches all fields in the class |
<method> |
Matches all methods in a class |
<init> |
Matches all constructors in a class |
* | Matches characters of any length, excluding package name delimiters (.) |
支那 | Matches characters of any length, including the package name delimiter (.) |
* * * | Matches any parameter type |
. | other |
1.4 Android unique @keep tag
By default, @keep is still confused because Android Studio does not enable this option by default. Add the following configuration to the confused configuration file proguard-rules.pro:
-keep class android.support.annotation.Keep -keep @android.support.annotation.Keep class * -keepclasseswithmembers class * { @android.support.annotation.Keep <methods>; } -keepclasseswithmembers class * { @android.support.annotation.Keep <fields>; } -keepclasseswithmembers class * { @android.support.annotation.Keep <init>(...) ; }Copy the code
⚠️ Note: at present, some information on the Internet shows that if @keep is added to a class, only the name of the class is logically not confused, but from the practical results, if @keep is added to the name of the class, the whole class cannot be confused.
1.5 Preserve Native methods
Theoretically, JNI layer-related methods should not be confused and removed directly even if they are not called, otherwise, registration failure will occur when JNI methods in registration mode are used in NDK.
-keepclasseswithmembers class * {
native <methods>;
}
Copy the code
In combination with the Keep keyword description, the above configuration can preserve the class and the named native method member functions in the class.
1.6 Preserve the UI-related classes of the Library project
The re-wrapped library project inevitably has some UI-related utility classes, and if this part is confused, the introduction will become unusable. We need to have non-confusing control over this part as well.
-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 -keepclassmembers class * extends android.app.Activity{ public void *(android.view.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); } # keep class **.R$* {*; }Copy the code
2. Enable obfuscation
This is not enabled by default in the Android Studio configuration and we need to manually enable it.
android {
...
buildTypes {
release {
minifyEnabled true // open ProGuard
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}}Copy the code
But this only works after every Release package, and we sometimes need to do obfuscation testing at Debug, where we can add a new buildType
android {
...
buildTypes {
release {
minifyEnabled true // open ProGuard
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debugMini {
initWith debug
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
matchingFallbacks = ['debug']}}}Copy the code
So we can choose buildVariants when the default Run we just new debugMini specified.
3. Summary
This short article should help many partners out of the pit, but more use or need to accumulate in the work. Some small experience eat all the obfuscation configuration without asking for a obfuscation command. We need fine configuration, and there are always some unpleasant things in general configuration. So let’s conduct one-to-one configuration for a single Class, and I believe we can get better obfuscation results.
That’s about it for this time. Welcome to leave a comment and discuss learning and progress together.
Thank you.