Запутывание или удаление строкового литерала во всех вызовах Log-функции в Android - PullRequest
1 голос
/ 05 июня 2019

Мы создаем приложение для Android, в котором мы используем Timber для Log-output.Мы определили наши собственные функции .e, .d, .v и т. Д. И используем if (BuildConfig.DEBUG), чтобы посмотреть, нужно ли выводить журнал.Это решает проблему, заключающуюся в том, что мы не хотим выводить журналы отладки в наших выпусках, но все строковые литералы, используемые в наших вызовах функций, все еще присутствуют в скомпилированном исходном коде.Кроме того, мы используем ProGuard для запутывания.Например, в классе мы можем иметь:

somObj.normalFunction(variable)
Log.d("This secret class achieved its secret mission!");

В нашем выпуске это не будет видно в журналах приложений, но если вы перепроектируете APK, вы увидите что-то вроде:

q.b(m)
z.a("This secret class achieved its secret mission!");

, который может дать подсказку хакерам о том, на какой класс они смотрят.Так что нам нужно либо иметь возможность УДАЛИТЬ все вызовы функций Log во время компиляции (используя некоторую предварительную обработку, аннотации или что-то еще, но, надеюсь, без необходимости добавлять что-либо перед КАЖДЫМ вызовом функции) ИЛИ скрывать всестроковые литеральные параметры для этих вызовов функций.Итак, два идеальных решения были бы, если бы источник, непосредственно перед компиляцией, выглядел так:

q.b(m);

или

q.b(m);
z.a("jgasoisamgp23mmwaföfm,ak,ä")

Просто думая, что я вижу два плохих способа добиться этого,Либо мы окружаем ВСЕ вызовы Log.d if(BuildConfig.DEBUG), что заставит компилятор удалить их перед компиляцией.Но это очень приливно.ИЛИ, мы уверены, что каждый раз, когда вы хотите добавить распечатку журнала, вам нужно сделать

Log.d(LogClass.getLog(1234)) 

, а затем вы определяете ВСЕ эти журналы внутри LogClass, а затем удаляете их с помощью if(BuildConfig.DEBUG) и возвращаете нуль вgetLog, если это так.Но каждый раз, когда вы хотите добавить журнал, это делает его более приличным.

Итак, наконец, есть ли ХОРОШЕЕ решение для этого?

Ответы [ 2 ]

1 голос
/ 07 июня 2019

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я работаю на PreEmptive , компанию, которая делает PreEmptive Protection - DashO .

DashO способна удалять вызовы для определенных методов (например, Logметоды).Хотя это не удаляет инструкции по загрузке строкового литерала, а только сам вызов, DashO также предлагает String Encryption, который обеспечит некоторую защиту этим строковым литералам.

В качестве примера я провел этот класс черезDashO:


    public class App {
        public static void main(String[] args) {
            Log.d("Secret message here"); 
        }
    }

После удаления вызовов на Log.d с включенным String Encryption декомпилированный вывод выглядит следующим образом:

    public class App
    {
      public static void main(String[] paramArrayOfString)
      {
        a.replace("Bwpfpb7u|ih}z{?($0&", -12 - -61);
      }
    }

DashO предлагает другие средства защиты (например, запутывание потока управления)которые имеют тенденцию ломать декомпиляторы;Я отключил их для этой демонстрации.

0 голосов
/ 05 июня 2019

Я бы сделал одно или несколько из следующих действий:

  1. Используйте Древесина (так что вам не нужно беспокоиться об удалении вещей или добавлении if операторов). Вы просто делаете это один раз в своем Application#onCreate(); если вы находитесь в DEBUG, то вы устанавливаете DebugTree, который печатает на консоль. Иначе, вы сажаете «пустое дерево», которое ничего не делает.

  2. Имитируйте Древесину , но создайте свой собственный класс "YourLogger" и сделайте то же самое (если вы не хотите включать стороннюю библиотеку, даже если это всего лишь один класс). Таким образом, у вас будет YourLogger.v("tag", "string"), а внутри вы сделаете: if (debug) { Log.v(tag, string); } и так далее, и так далее для всех других типов журналов.

  3. Используйте Proguard для удаления записи, а что нет.

1 и 2 означают, что вы просматриваете приложение и заменяете все строки Log. на Timber. или YourLogger. Варианту 3 это не понадобится, поскольку код будет удален во время запутывания, и вызовы ничего не сделают, но это сложный режим (а я не делал этого годами, даже не помню, как это было сделано, возможно, легко) посмотреть)

Я бы пошел на 1.

Обновление

Поскольку, очевидно, я не знаю, как читать, я думаю, что для достижения этой цели ваша единственная ставка - иметь какой-то механизм поиска для реального текста, который вы хотите испустить / скрыть.

Strings.xml является самым простым, так как он включен в Android, и вы даже можете локализовать сообщения об ошибках (если, конечно, это было необходимо). Да, есть штраф за время поиска, но я бы сказал, что если вы не перебираете более тысячи элементов и каждый раз регистрируете разные строки, штраф не будет заметным (у меня нет данных для этого, вы бы должны ориентироваться).

В качестве альтернативы, вместо того, чтобы полагаться на ресурсы, вы можете просто использовать файл, прочитать его и загрузить строки в память ... компромисс; Вы используете больше памяти за счет простоты и времени для написания кода решения, или вы используете встроенный механизм и платите процессорное время?

...