Отражение против Proguard даже с не переименованным классом - PullRequest
0 голосов
/ 30 октября 2019

Я собираюсь полностью отказаться от запутывания! У меня есть основное приложение, которое использует несколько apks в качестве плагинов, запускающих свои сервисы и импортирующих их фрагменты в MainActivity. Это немного сложно, но может быть сделано со знанием всех имен классов и рефлексии.

Теперь идет обуфкация. Я знал, что мне нужно защитить все классы фрагментов, чтобы иметь возможность доступа к их классам через строковые константы и загрузчик классов.

Давайте начнем с StartupFragment, который является внутренним в основном приложении. Фрагмент моего proguard-rules.pro:

-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable,InnerClasses,Signature,*Annotation*
-keeppackagenames com.my.company.**

-keep public class * extends com.my.company.plugin.MyFragmentExtension{
    public <methods>;
    public static <fields>;
}

Похоже, что keeppackagenames и the keep расширяют работу: я проверил apk с помощью: apk-> unzip-> dex2jar classes.dex -> jd-gui dex2jar.jar И StartupFragment находится прямо внутри полностью именованного пакета.

Теперь я написал небольшой тест:

 try
    {
        Fragment direct = new StartupFragment(); //always works OK!
        Log.d(TAG,TAG + " CLTEST: StartupFragment created directly");
        Fragment reflect = null;
       //Classloader taken right from the class I want to load via reflection
        ClassLoader cl = StartupFragment.class.getClassLoader(); 
       //reflection load always fails ClassNotFoundException
        Class classss= cl.loadClass(StartupFragment.class.toString()); 
        Log.d(TAG, TAG +  " CLTEST: "+StartupFragment.class.toString() +".class loaded via reflection via OWN classloader");
        reflect = (Fragment)classss.newInstance();

    }catch (ClassNotFoundException e)
    {
        Log.e(TAG,TAG + " CLTEST StartupFragment classloader has failed to find " + StartupFragment.class.getName());
        e.printStackTrace();
    }catch (Throwable e)
    {
        Log.e(TAG,TAG + " CLTEST StartupFragment classloader has failed: ",e);
        e.printStackTrace();
    }

Вопрос теперь таков: почему загрузчик классов мог взятьиз самого класса он должен загрузить сбой, даже если класс не был переименован (и даже имя взято непосредственно из класса) ??

Дополнительная информация:

  • безobfuscation (minifyEnabled false) все отлично работает с отражением
  • com.my.company.plugin.MyFragmentExtension находится в пакете aar, но это не должно быть проблемой, поскольку класс сохранен и не переименован?!
  • все внутренние классы StartupFragment (как и все, например, onClickListeners) были переименованы и удалены из исходного класса (см. Dex2jar.jar)
...