Обфускация кода под Android

by dilix
Обфускация. Защита с Proguard.

Защита кода приложения это то, о чем не всегда задумывается разработчик. Но  ведь обфускация при сборке — это не только защита. Это также эффективный способ уменьшить размер конечного APK, а иногда и оптимизировать исполнение программы. В этом нам поможет Proguard.

С учетом того, на сколько сейчас просто настроить Proguard для разработки под Android, не использовать эту возможность крайне не логично.

Интересный факт: существует контест на написание самого креативного обфусцированного кода на СИ «The International Obfuscated C Code Contest». Можно посмотреть на разные примеры эпичного компилируемого кода.

Что делает Proguard?

Proguard — наверное самый часто используемый инструмент для обфускации кода при разработке под Андроид. Он бесплатный, с открытым исходным кодом. Есть еще DexGuard для более продвинутой защиты вашего приложения.

Удаление неиспользуемого кода

Неиспользуемый код — лишние байты информации. Обфускация и Proguard удаляет его, экономя на финальном размере Apk.

Надо быть осторожным, код может использовать через рефлексию, в таком случае обфусцированное приложение сломается у пользователя на устройстве.

Оптимизация байт кода

Proguard умеет работать с исходниками на уровне байткода, применяя оптимизации, например такие как

  • Замена умножение и деление на степень двойки на сдвиг,
  • Inline интерфейсов с единственной реализацией,
  • Подмена по возможности enum на численные константы,
  • и другие полезные вещи.

Надо понимать, что Proguard работает на уровне Java байт кода, в то время как Андроид приложения исполняются на Dalvik Virtual Machine (DVM) используя Dalvik байт код. Оптимизации одного кода могут плохо отразиться на втором. А это значит надо внимательно относится к данному процессу.

Как настроить Proguard для Android?

Максимально подробную инструкцию от первоисточника можно найти в официальной документации Андроида, пройдемся по порядку:

Изменить build.gradle

android {
    ...
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
}
  • getDefaultProguardFile('proguard-android.txt') — базовый конфиг для Андроид приложения из Android SDK, по умолчанию в нем отключена оптимизация, т.к. Dex может ее не пережить, попробовать ее включить можно, использовав вместо этого getDefaultProguardFile('proguard-android-optimize.txt')
  • proguard-rules.pro — конфигурация непосредственно вашего модуля

Не следует включать обфускацию для Debug сборок, потому как этот процесс занимает время. Зачем тратить его просто на ожидание на этапе разработки?

Добавить config для используемых библиотек

Редко когда приложение не использует сторонние библиотеки. А внешние модули часто требуют дополнительных настроек для Proguard. Но! Существует проект на GitHub — сборник сниппетов для популярных библиотек, в котором уже есть большинство нужных конфигов.

Достаточно положить все файлы настроек в папку proguard  вашего модуля (по умолчанию app ) и добавить в build.gradle строку, чтобы блок, отвечающий за proguard выглядел следующим способом:

minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt')
proguardFiles(file('./proguard').listFiles())

proguardFiles(file('./proguard').listFiles())  возьмет все файлы конфигов из папки proguard и применит их при обфускации вашего приложения.


Проверить, что ваше приложение работает

Нужно проверять не Debug сборку без обфускации, а именно «оптимизированное» приложение. Лично я часто натыкался на то, что у меня все работает, а у тестировщиков сломано. Далеко не сразу соображаешь, что дело именно в ProGuardе.

Проверить сериализацию данных после обфускации

Большинство приложений сегодня работает с бэкендом. Запрос и ответ зачастую описан примерно таким классом

public final class BookResponse {
    private String author;
    private String title;
}

и все корректно работает. Мы получаем данные. Все хорошо.

Приложение уходит тестировщику, у которого опять все сломано. Дело в том, что при обфускации меняются в том числе имена приватных методов, полей и другой «служебной» информации. В следствии чего при автоматическом парсинге JSON сериализатор будет искать поле не author , а не пойми какое.

Решений по сути есть 2

  1. Запретить обфускацию классов, участвующих в сетевом обмене на уровне конфигурации модуля,
  2. Добавить имя для сериализации.

Я выбираю второе по нескольким причинам

  • Имя параметра не зависит от имени параметра на сервере,
  • Руководствуясь AOSP Java Code Style for Contributors все не публичные члены класса у меня имеют префикс m,
  • Смена имени на бэкенде при рефакторинге приведет к изменению ровно одного значения.

В итоге данный класс будет выглядеть следующий образом

public final class BookResponse {
    @SerializedName("author")
    private String mAuthor;
    @SerializedName("title")
    private String mTitle;
}

Все, обфускация готова!

Описанного выше достаточно, чтобы настроить ProGuard для защиты вашего проекта. Как видите, ничего сложного нет, обычно 5-10 минут работы и ваше приложение как-никак, но защищено от статического анализа кода. А защитить приложение от не санкционированного доступа поможет экран пин кода на старте.

DexGuard

Если вам нужна только базовая обфускация и оптимизация, то ProGuard — то что вам нужно. Ваше приложение или библиотека требуют более серьезной защиты? Тогда следует посмотреть в сторону коммерческого DexGuard. Основные отличия между двумя инструментами:

ProGuardDexGuard
Оптимизация Java байт кодаКомплексная защита Андроид приложения, включающая в себя тюнингованные версии часто используемых библиотек (Google play service, Dagger, Realm, SQLCipher и др.)
Базовая защита от статического анализа кодаЗащита как от статического так и от динамического анализа приложения
Фокус на байт коде приложенияОптимизация, обфускация и шифрование файлов манифеста, нативных библиотек, файлов ресурсов и тд.
Усложнение реверс инжениринга путем переименования классов методов и тд.Помимо базовой, обфускация арифметический и логических операция, контроль порядка выполнения методов, шифрования строк и классов, добавление рефлексии для доступа к критическим данным
Инструмент с открытым исходным кодомКоммерческий инстурмент, требующий лицензии

Возможные проблемы

  • Java 8 и DexGuard
    • При использовании одной библиотеки, которая обфусцирована с помощью DexGuard, возникли непреодолимые трудности с использованием Java 8 еще на этапе компиляции
  • Надо не забывать сохранять корректный map file, чтобы в дальнейшем упростить дебаг приложения. Если этого не сделать, строки в stack trace будут не совпадать с тем, что вы видите в коде.

Когда мы разобрались как работает обфускация, время перейти к полезным инструментам для Андроид разработчика.

Хочешь обсудить Android разработку?
Заходи к нам Вконтакте, на Facebook и в Телеграм!

Добавить комментарий

Может быть интересно

Этот сайт использует Cookie файлы для улучшения вашего пользовательского взаимодействия. Используя данный сайт вы соглашается с этим. Принять Читать

Политика конфиденциальности и Cookies