- ProGuard
- ProGuard
- In this document
- See also
- Enabling ProGuard (Gradle Builds)
- Enabling ProGuard (Ant Builds)
- Configuring ProGuard
- Decoding Obfuscated Stack Traces
- Debugging considerations for published applications
- ProGuard. Часть 1. 95% граблей
- Что такое ProGuard
- Историческая справка
- ProGuard и Android
- Сторонние библиотеки
- Android и ProGuard
- Как увидеть результат работы ProGuard
- Заключение
ProGuard
ProGuard — утилита, которая удаляет из готового кода неиспользуемые фрагменты и изменяет имена переменных и методов для усложнения реверс-инжиниринга приложения. Также позволяет уменьшить размер загружаемых на устройство файлов.
Во время своей работы утилита совершает несколько последовательных шагов.
На первом шаге Proguard рекурсивно определяет, какие классы и члены классов (переменные, методы, константы) используются. Все другие классы или члены классов будут удалены из приложения.
Следующий шаг — оптимизация. Proguard может поменять модификаторы классов и методов, удалить неиспользуемые параметры и т.д. Не всегда подобная оптимизация идёт на пользу, поэтому часто этот шаг пропускают.
Важная часть — обфускация. ProGuard переименовывает классы и члены классов, которые не являются точками входа. Точки входа сохраняют свое оригинальное название. Это затрудняет декомпиляцию и исследование работы приложения (reverse engineering).
В Android не используется, но для обычных приложений Java также используется дополнительный шаг — проверка, что код не может случайно или намеренно вырваться из песочницы виртуальной машины Java. Для того, чтобы эта проверка проходила быстрее, компилятор добавляет к файлам классов дополнительную информацию. Соответственно, ProGuard должен в конце своей работы сформировать новую информацию для этой проверки.
В приложении под Android пользовательский интерфейс чаще всего описывается с помощью XML. Часть классов, использующихся при описании интерфейса, нигде в коде не используется. Поэтому, если не сообщить об этих классах ProGuard, они будут удалены. XML с описаниями интерфейса в процессе сборки анализируются аналогично AndroidManifest.xml, и все перечисленные там классы добавляются в файл конфигурации для ProGuard.
Сформированный файл сохраняется в в app/build/intermediates/proguard-rules/debug/aapt_rules.txt.
Второй файл конфигурации Proguard, который по умолчанию используется при сборке приложения под Android, приходит в составе SDK. Этот файл явно указан в build.gradle нашего приложения.
proguard-android.txt — это дефолтный файл конфигурации, поставляемый с SDK. Экспериментаторы могут заменить его на proguard-android-optimize.txt.
proguard-rules.pro — файл, в который предлагается писать свои директивы для ProGuard. Изначально пустой, находится в каталоге приложения.
Вы можете включить ProGuard не только для release, но и для debug версий. Это очень полезно, потому что поведение приложения с включенным ProGuard может отличаться от приложения с выключенным ProGuard совершенно неожиданным образом. Чем раньше все эти неожиданности будут обнаружены и исправлены, тем лучше. За включение ProGuard отвечает директива minifyEnabled.
Если нет уверенности в правильности работы ProGuard, имеет смысл выключить обфускацию. Для этого добавьте в proguard-rules.pro следующую директиву:
Конфигурации для всех сторонних библиотек, которые вы взяли в android-proguard-snippets, храните в каталоге proguard внутри каталога вашего приложения. Тогда подключить сразу весь каталог можно с помощью следующей директивы в build.gradle:
Очень часто возникают проблемы с ProGuard при подключении сторонних библиотек. Обычно, авторы библиотек прикладывает к описанию необходимые комментарии для решения проблемы.
Источник
ProGuard
In this document
See also
The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. The result is a smaller sized .apk file that is more difficult to reverse engineer. Because ProGuard makes your application harder to reverse engineer, it is important that you use it when your application utilizes features that are sensitive to security like when you are Licensing Your Applications.
ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended.
This document describes how to enable and configure ProGuard as well as use the retrace tool to decode obfuscated stack traces.
Enabling ProGuard (Gradle Builds)
When you create a project in Android Studio or with the Gradle build system, the minifyEnabled property in the build.gradle file enables and disables ProGuard for release builds. The minifyEnabled property is part of the buildTypes release block that controls the settings applied to release builds. Set the minifyEnabled property to true to enable ProGuard, as shown in this example.
The getDefaultProguardFile(‘proguard-android.txt’) method obtains the default ProGuard settings from the Android SDK tools/proguard/ folder. The proguard-android-optimize.txt file is also available in this Android SDK folder with the same rules but with optimizations enabled. ProGuard optimizations perform analysis at the bytecode level, inside and across methods to help make your app smaller and run faster. Android Studio adds the proguard-rules.pro file at the root of the module, so you can also easily add custom ProGuard rules specific to the current module.
You can also add ProGuard files to the getDefaultProguardFile directive for all release builds or as part of the productFlavor settings in the build.gradle file to customize the settings applied to build variants. This example adds the proguard-rules-new.pro to the proguardFiles directive and the other-rules.pro file to the flavor2 product flavor.
Enabling ProGuard (Ant Builds)
When you create an Android project, a proguard.cfg file is automatically generated in the root directory of the project. This file defines how ProGuard optimizes and obfuscates your code, so it is very important that you understand how to customize it for your needs. The default configuration file only covers general cases, so you most likely have to edit it for your own needs. See the following section about Configuring ProGuard for information on customizing the ProGuard configuration file.
To enable ProGuard so that it runs as part of an Ant or Eclipse build, set the proguard.config property in the
/project.properties file. The path can be an absolute path or a path relative to the project’s root.
If you left the proguard.cfg file in its default location (the project’s root directory), you can specify its location like this:
You can also move the the file to anywhere you want, and specify the absolute path to it:
When you build your application in release mode, either by running ant release or by using the Export Wizard in Eclipse, the build system automatically checks to see if the proguard.config property is set. If it is, ProGuard automatically processes the application’s bytecode before packaging everything into an .apk file. Building in debug mode does not invoke ProGuard, because it makes debugging more cumbersome.
ProGuard outputs the following files after it runs:
dump.txt Describes the internal structure of all the class files in the .apk file mapping.txt Lists the mapping between the original and obfuscated class, method, and field names. This file is important when you receive a bug report from a release build, because it translates the obfuscated stack trace back to the original class, method, and member names. See Decoding Obfuscated Stack Traces for more information. seeds.txt Lists the classes and members that are not obfuscated usage.txt Lists the code that was stripped from the .apk
These files are located in the following directories:
/bin/proguard if you are using Ant.
/proguard if you are using Eclipse.
Caution: Every time you run a build in release mode, these files are overwritten with the latest files generated by ProGuard. Save a copy of them each time you release your application in order to de-obfuscate bug reports from your release builds. For more information on why saving these files is important, see Debugging considerations for published applications.
Configuring ProGuard
For some situations, the default configurations in the ProGuard configuration file will suffice. However, many situations are hard for ProGuard to analyze correctly and it might remove code that it thinks is not used, but your application actually needs. Some examples include:
- a class that is referenced only in the AndroidManifest.xml file
- a method called from JNI
- dynamically referenced fields and methods
The default ProGuard configuration file tries to cover general cases, but you might encounter exceptions such as ClassNotFoundException , which happens when ProGuard strips away an entire class that your application calls.
You can fix errors when ProGuard strips away your code by adding a -keep line in the ProGuard configuration file. For example:
There are many options and considerations when using the -keep option, so it is highly recommended that you read the ProGuard Manual for more information about customizing your configuration file. The Overview of Keep options and Examples sections are particularly helpful. The Troubleshooting section of the ProGuard Manual outlines other common problems you might encounter when your code gets stripped away.
Decoding Obfuscated Stack Traces
When your obfuscated code outputs a stack trace, the method names are obfuscated, which makes debugging hard, if not impossible. Fortunately, whenever ProGuard runs, it outputs a mapping.txt file, which shows you the original class, method, and field names mapped to their obfuscated names.
The retrace.bat script on Windows or the retrace.sh script on Linux or Mac OS X can convert an obfuscated stack trace to a readable one. It is located in the /tools/proguard/ directory. The syntax for executing the retrace tool is:
If you do not specify a value for , the retrace tool reads from standard input.
Debugging considerations for published applications
Save the mapping.txt file for every release that you publish to your users. By retaining a copy of the mapping.txt file for each release build, you ensure that you can debug a problem if a user encounters a bug and submits an obfuscated stack trace. A project’s mapping.txt file is overwritten every time you do a release build, so you must be careful about saving the versions that you need. For Eclipse, this file is stored in
/bin/proguard/ . For Android Studio, this file is stored in the app build/outs/ folder.
Источник
ProGuard. Часть 1. 95% граблей
ProGuard — утилита, которая удаляет из скомпилированного кода неиспользуемые фрагменты и изменяет имена переменных и методов для усложнения реверс-инжиниринга приложения. В разработке под Android эта утилита необходима в первую очередь для уменьшения размера загружаемых на устройство файлов.
Я планирую написать две статьи о ProGuard. В этой я расскажу о добавлении ProGuard в проект и дам несколько советов, которые с вероятностью 95% решат вашу задачу. В следующей статье мы подробнее рассмотрим работу инструмента и разберем, что делать, если советов из первой статьи недостаточно.
Что такое ProGuard
Разработчики утверждают, что ProGuard — это shrinker, optimizer, obfuscator и preverifier. Ни одно из этих слов не переводится на русский без оговорок. Эти четыре слова обозначают четыре последовательных этапа работы ProGuard.
Shrinking step На этом шаге ProGuard начиная от точек входа в программу рекурсивно определяет, какие классы и члены классов (переменные, методы, константы) используются. Все другие классы или члены классов будут удалены из приложения.
Optimization step ProGuard может классы и методы, которые не являются точками входа, сделать private, final, static, удалить неиспользуемые параметры, “встроить” (inline) методы, и т.д.
Оптимизация силами ProGuard’а приложений под Android часто вреда приносит больше, чем пользы, поэтому по умолчанию этот шаг пропускают. Если появится желание поэкспериментировать, посмотрите сначала, что написано в родном файле конфигурации.
Obfuscation step ProGuard переименовывает классы и члены классов, которые не являются точками входа. Точки входа сохраняют свое оригинальное название. Это затрудняет декомпиляцию и исследование работы приложения (reverse engineering).
Preverification step Виртуальная машина Java при загрузке классов проводит проверку, что код не может случайно или намеренно вырваться из песочницы виртуальной машины. Для того, чтобы эта проверка проходила быстрее, компилятор добавляет к файлам классов дополнительную информацию. Соответственно, ProGuard должен в конце своей работы сформировать новую информацию для этой проверки. Для приложений под Android это не требуется.
Историческая справка
ProGuard — open source проект под руководством Эрика Лафортуне (Eric Lafortune), первый релиз был в 2002 году, с конца 2010 года входит в состав Android SDK.
ProGuard и Android
Точками входа в приложение являются Activity и другие компоненты, указанные в AndroidManifest.xml. Сам ProGuard про AndroidManifest.xml ничего не знает, для него в процессе сборки формируется файл конфигурации, в котором перечислены классы всех компонент. Чуть позже мы заглянем внутрь этого файла.
ProGuard рекурсивно, начиная с точек входа, составляет список всех классов и их членов, которые используются в коде. После того, как список сформирован, все классы и члены, в него не попавшие, будут удалены. Но для работы приложения должны сохраниться классы и методы, вызываемые с помощью рефлексии (reflection), а также аннотации, используемые во время выполнения. Список того, к чему доступ осуществляется с помощью рефлексии, путем анализа скомпилированных классов составить невозможно, поэтому они также должны быть указаны явно с помощью файла конфигурации.
В приложении под Android пользовательский интерфейс чаще всего описывается с помощью XML. Часть классов, использующихся при описании интерфейса, нигде в коде не используется, и, если не сообщить об этих классах ProGuard’у, они будут удалены. Поэтому XML с описаниями интерфейса в процессе сборки анализируются аналогично AndroidManifest.xml, и все перечисленные там классы добавляются в файл конфигурации для ProGuard.
Текущая версия build tools помещает сформированный файл в app/build/intermediates/proguard-rules/debug/aapt_rules.txt
Вот фрагмент этого файла, в нем видно, что после анализа XML был автоматически сформирован список классов, которые необходимо сохранить:
Подробнее о директивах ProGurad я расскажу в следующей статье: того, что можно понять из названия директивы, нам сейчас вполне достаточно.
Второй файл конфигурации Proguard, который по умолчанию используется при сборке приложения под Android, приходит в составе SDK. Посмотреть на него можно здесь. Этот файл явно указан в build.gradle нашего приложения. О конфигурации Proguard в build.gradle будет рассказано чуть позже.
Сторонние библиотеки
Самое интересное присходит, когда в приложение требуется добавить стороннюю библиотеку, которая в работе использует рефлексию. Яркие примеры — это Retrofit и ButterKnife.
Если не настроить ProGuard для таких библиотек, то в лучшем случае мы получим падение приложения, в худшем — поведение приложения не будет соответствовать ожидаемому, и это может привести к потере времени на отладку. Поскольку проблема эта возникла достаточно давно, то авторы библиотек начали приводить пример конфигурации ProGuard в документации. Со временем появилась возможность добавить конфигурацию ProGuard прямо в библиотеку. Авторы многих (но не всех) библиотек это сделали.
Если любопытно, поищите файлы proguard.txt в каталоге app/build/intermediates/exploded-aar/. Вот, например:
Теперь о библиотеках, которые не содержат правила для ProGuard. Если вы используете что-то из уже проверенных сообществом библиотек, то с большой вероятностью конфигурацию можно найти вот на этом ресурсе.
Убедитесь только, что в зависимостях вашего приложения указана последняя версия библиотеки, потому что со временем требования к настройке ProGuard могут меняться.
Android и ProGuard
По умолчанию build.gradle приложения содержит следующий раздел:
proguard-android.txt — это дефолтный файл конфигурации, поставляемый с SDK, я про него уже писал. Смелые экспериментаторы, желающие поиграть с оптимизацией, могут заменить его на proguard-android-optimize.txt.
proguard-rules.pro — файл, в который предлагается писать свои директивы для ProGuard. Изначально пустой, находится в каталоге приложения.
Рецепт будет таким:
Первое — включить ProGuard не только для release, но и для debug версий. Это очень полезно, потому что поведение приложения с включенным ProGuard может отличаться от приложения с выключенным ProGuard совершенно неожиданным образом. Чем раньше все эти неожиданности будут обнаружены и исправлены, тем лучше. Не откладывайте включение ProGuard на день сборки релиза, это может стоить вам нескольких бессонных ночей.
За включение ProGuard отвечает директива minifyEnabled . Включенному ProGuard соответствует
Второе — до тех пор, пока нет уверенности в правильности работы ProGuard, имеет смысл выключить обфускацию. Для этого добавьте в proguard-rules.pro следующую директиву:
Третье — конфигурации для всех сторонних библиотек, которые вы взяли в android-proguard-snippets, храните в каталоге proguard внутри каталога вашего приложения. Тогда подключить сразу весь каталог можно с помощью следующей директивы в build.gradle :
В приложении, над которым я сейчас работаю, эта папка выглядит так:
В итоге build.gradle получается вот такой:
Как увидеть результат работы ProGuard
Можно воспользоваться APK Analyzer (Build -> Analyze APK… в Android Studio). Соберите два apk с включенным и с выключенным ProGuard и сравните их. Должна быть заметна разница (не обязательно такая большая):
Если вы знаете в своем коде какие-то неиспользуемые методы или классы, то откройте apk с помощью APK Analyzer и попробуйте внутри classes.dex их найти. Если ProGuard отработал корректно, то их там не должно быть.
Другой способ. ProGuard формирует 4 текстовых файла с отчетами о своей работе. Один из них — usage.txt — содержит список классов и членов, которые были удалены. Найдите этот файл и загляните внутрь, при правильной работе он всегда не пустой. Лежат эти файлы, как правило, в каталоге app/build/outputs/mapping
Заключение
Я очень надеюсь, что эта статья поможет сохранить время и силы в настройке ProGuard. Если у вас есть хорошие советы относительно ProGuard, или вы попали в оставшиеся 5%, поделитесь этим в комментариях внизу, на вопросы я постараюсь ответить в следующей статье.
Источник