Обфускация кода с ProGuard и JAXB
опубликовано: ⏰ 3
ProGuard – это мощный инструмент, который позволяет не только обфусцировать код, но и оптимизировать его, удаляя ненужные классы, методы и поля. Это помогает сократить размер финального приложения и сделать процесс реверсинжиниринга вашего кода более трудным.
JAXB, с другой стороны, предоставляет простой способ преобразования Java-объектов в XML и обратно. Однако использование JAXB может привести к тому, что некоторые классы и методы остаются доступными извне, что может быть нежелательно с точки зрения безопасности.
В этой небольшой заметке покажу, как настроить ProGuard таким образом, чтобы он корректно работал с JAXB.
Основные проблемы при использовании ProGuard с JAXB
Обфускация кода с JAXB требует особого внимания, так как JAXB использует рефлексию для доступа к полям и методам классов. Если ProGuard переименует эти элементы или удалит их, то JAXB не сможет корректно работать с вашими объектами.
То же самое касается перечислений (enum) и аннотаций, которые также могут быть повреждены при обфускации. При включенной
оптимизации !class/unboxing/enum (
см. Документацию ProGuard по оптимизациям), часть
перечислений может быть заменена на числовые константы.
Настройка ProGuard для работы с JAXB
Для решения проблем с переименованием классов и атрибутов достаточно использовать стандартные аннотации, указывающие на настоящие названия элементов и атрибутов. Например:
@XmlType(name = "documentType")
@XmlRootElement(name = "document") // <1>
public final class Document {
@XmlElement(name = "name") // <2>
private String name;
@XmlElement(name = "type")
private Type type;
@XmlEnum
@XmlType(name = "sourceType")
public enum Source {
LOCAL,
REMOTE
}
}- Определяет имя корневого элемента XML.
- Определяет имя элемента XML для поля
name.
При десериализации и сериализации JAXB будет использовать указанные имена из аннотаций, а не переименованные ProGuard.
Для того чтобы ProGuard правильно обрабатывал классы, используемые JAXB, необходимо добавить соответствующие правила в конфигурационный файл.
-optimizations !class/unboxing/enum # <1>
-keepattributes InnerClasses,Signature,LineNumberTable,*Annotation*,EnclosingMethod # <2>
-keepclassmembers enum com.test.jaxb.** { # <3>
<fields>; # <4>
public static **[] values();
public static ** valueOf(java.lang.String);
}- Отключает оптимизацию, которая может привести к проблемам с перечислениями.
- Сохраняет атрибуты, необходимые для работы JAXB.
- Сохраняет членов класса перечислений в указанном пакете.
- Сохраняет все поля перечислений.
Дополнительно – Java SPI
В случае использования Java SPI так же могут быть проблемы из-за оптимизаций ProGuard и переименования классов. Списки
доступных сервисов хранятся в ресурсах META-INF/services/, и важно, чтобы имя интерфейса соответствовало полному имени
класса.
Для того чтобы ProGuard не переименовал интерфейсы SPI, нужно указать их в конфигурационном файле. Например:
-keepnames class com.test.spi.HardwareMemoryProvider // <1>- Достаточно сохранять полный путь к классу.
Заключение
Использование ProGuard для оптимизации и сокращения размера JAR может привести к проблемам при работе JAXB и Java SPI. Однако, указав соответствующие правила, можно избежать этих проблем.