Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard keep public classes, fields and methods

I use Kotlin and I have many internal classes. I want to obfuscate and shrink everything apart from all public classes.

Proguard rules:

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

-optimizationpasses 5
-overloadaggressively
-repackageclasses ''
-allowaccessmodification

-keep public class * {
    public <methods>;
    public <fields>;
}

Unfortunately the -keep public class * behaves defensively and keeps all names, also for the internal classes.

like image 350
Diolor Avatar asked Jan 29 '18 20:01

Diolor


1 Answers

Your rules are way too broad.

  1. Single "-keep" with nested rules is more broad, compared to combination of "-keepmembers" and "-keepclasseswithmembers" rules
  2. Full "-keep" rule means "do not change bytecode of that method, ever"
  3. Classes, referenced by kept classes and methods, can not be removed, renamed or repackaged

This line in your rules keeps all your classes and interfaces:

-keep public class * {

I mean ALL of them. Whether they have public members or not.

Use -keepclasseswithmembers instead!

Because of these lines

{
    public <methods>;
    public <fields>;
}

all your public methods will be left untouched, which means that repackaging and renaming methods, referenced from your public methods can not be carried out!

If you want at least some repackaging to be done, make sure to allow optimization (because repackaging is performed as part of optimization step):

-keepmembers,allowoptimization public class * {
    public <methods>;
    public <fields>;
}

In addition to repackaging, this will also allow for some inlining (which in turn assists in removing classes, that supply inlined methods).

Also with Android apps you are much better off repackaging into your primary package (the application package, or package with biggest number of your immovable classes in it) instead of empty package (''). This is because some "exported" classes (Activities, Views, Services, other stuff, referenced from xml files) can not be moved outside of their package by Proguard, — aapt dynamically generates special rules to prevent that. The part of optimization process, that changes access modes from public to protected/private, becomes more efficient the more classes can be placed together in single package.

I want to obfuscate and shrink everything apart from all public classes.

Bad idea. You really should try to obfuscate as much as possible, especially public classes. If you restrict obfuscation, repackaging is also restricted! It would rename them!!

Aim for the most specific rules possible.

If you want to prevent shrinking:

-keep,allowoptimization,allowobfuscation public class com.example.Example

If you want to prevent renaming, but allow stripping unused classes:

-keep,allowoptimization,allowshrinking public class com.example.*

In general, avoid wildcard rules (bare *) and -keep rules: prefer rules for specific classes and -keepmembers/-keepclasseswithmembers


The correct approaches for obfuscating applications and libraries are completely different, but they have something in common — you should not care about public methods/classes; just obfuscate/shrink/repackage as much as possible until any more would break it.

For applications you should just obfuscate/repackage as much as possible. If you don't know, which packages are safe to obfuscate, start from opting known safe packages into obfuscation.

For libraries — do not apply Proguard to library itself (unless you are trying to achieve security by obscurity). Use the feature of aar format — consumer proguard files — that allows to supply rule "segments", which should be followed during final app obfuscation.

like image 119
user1643723 Avatar answered Nov 15 '22 08:11

user1643723