BERDAFLEX Software Systems  
Главная > Eclipse > Статьи > Защита приложений на платформе Eclipse RCP

Защита приложений на платформе Eclipse RCP

История переиздания
Издание 1.0 2008.09.04 Сергей Бердачук

Наконец наступил момент когда вы готовы показать ваше творение миру. И если это коммерческое приложение, то желательно сразу же позаботиться о защите программного кода от взлома злоумышлиниками.

Для написанных на языке java программ это существенная проблема, так как существует несколько программ, которые позволяют декомпилировать java байт код обратно в тестовый формат java файлов проекта. Одним из наиболее известных и популярных декомпиляторов на данный момент является продукт Павла Кузнецова (Pavel Kouznetsov) под названием JAD .

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

Используя автоматически генерируемый шаблон приложения создадим простой Eclipse RCP проект. Для этого вызовем мастер из меню: «File->New->Plug-in Development->Plugin Project». Во второй закладке мастера дадим имя проекту «com.berdaflex.obfuscatedmail». На следующей странице выберем радиокнопку для указания того, что это Rich Client Application. На последней странице мастера выберем шаблон проекта «RCP Mail Template» и нажимаем кнопку «Finish». Для удобства развертывания (создания автономного) приложения создадим файл конфигурации продукта. Для этого указываем мышкой на проект в панели навигатора и нажатием правой кнопки мыши вызываем контекстное меню. В этом меню выбираем «New->Product Configuration». В настройках задаем имя продукта «obfuscatedmail» и из возможных вариантов инициализации выбираем вариант инициализации на базе готового продукта «Use an existing product» указав продукт «com.berdaflex.obfuscatedmail.product». При открытии данного файла у нас появляется возможность экспорта продукта (линк «Eclipse product export wizard.»). Выполним экспорт продукта и проанализируем, что у нас получилось.

В ходе экспорта продукта создается каталог продукта с файлом для его запуска, а так же несколько дополнительных папок среди которых нас интересует содержимое папки «plugins». В данной папке наряду с jar пакетами от которых зависит ваше приложение будет создан пакет «com.berdaflex.obfuscatedmail_1.0.0.jar» который содержит основной код приложения и который мы сейчас взломаем, а потом будем защищать от злоумышленников.

Распаковываем данный jar в отдельную папку (можно воспользоваться любым архиватором, который позволяет работать с zip архивами). Для удобства декоомпиляции сразу множества классов рекурсивно в дочерних каталогах автор написал простую утилиту RecurseExecute.exe на вход которой подается команда которую нужно выполнить для всех дочерних каталогов. Данную утилиту, файл декомпилятора jad, скрипты пакетного запуска decJava.bat и delClasses.bat желательно скопировать в каталог который входит в системные пути, чтобы их можно было вызывать из командной строки.

Заходим в каталог с распакованным архивом и набираем команду:

decJava.bat

для декмпиляции классов, а потом команду:

delClasses.bat

для удаления всех откомпилированных классов, так как они нас больше не интересуют.

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

break MISSING_BLOCK_LABEL_XXX

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

public Object start(IApplicationContext context)
{
   Display display = PlatformUI.createDisplay();
   Integer integer;
   int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
   if(returnCode != 1)
     break MISSING_BLOCK_LABEL_33;
   integer = IApplication.EXIT_RESTART;
   display.dispose();
   return integer;
   integer = IApplication.EXIT_OK;
   display.dispose();
   return integer;
   Exception exception;
   exception;
   display.dispose();
   throw exception;
}

довольно просто можно исправить к работающему блоку вида:

public Object start(IApplicationContext context) {
    Display display = PlatformUI.createDisplay();
    Integer integer;
    int returnCode = PlatformUI.createAndRunWorkbench(display,
      new ApplicationWorkbenchAdvisor());
    if (returnCode == 1) {
      integer = IApplication.EXIT_RESTART;
      display.dispose();
      return integer;
    } else {
      integer = IApplication.EXIT_OK;
      display.dispose();
      return integer;
    }
}

В оригинальном приложении данный блок кода имел следующую реализацию:

public Object start(IApplicationContext context) {
  Display display = PlatformUI.createDisplay();
  try {
    int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
    if (returnCode == PlatformUI.RETURN_RESTART) {
      return IApplication.EXIT_RESTART;
    }
    return IApplication.EXIT_OK;
  } finally {
    display.dispose();
  }
}

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

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

Для приложений Eclipse RCP есть ряд проблем по использованию обфускаторов. Основной из которых является необходимость оставлять классы и методы, которые используются в публичных интерфейсах в том же виде, в котором они описаны.

К счастью это легко решается в соответствии с основными принципами инкапсуляции например введением дополнительной иерархии классов с внутренней реализацией, которая не будет доступна извне для внешних подключаемых модулей. В проекте Eclipse принята практика такие классы помещають в дочерние пакеты вида: <имя базового пакета>.internal.<имя пакета>

В ходе рефакторинга исходного проекта публичные классы разбиваем на два, например:

package com.berdaflex.obfuscatedmail;

. . .

public class Application implements IApplication {
. . .
}

будет преобразован в два класса:

package com.berdaflex.obfuscatedmail;

. . .

public class Application extends ApplicationInternal {
 // реализация перенесена во внутренний класс
}

и

package com.berdaflex.internal.obfuscatedmail;

. . .

public class ApplicationInternal implements IApplication {
. . .
 // внутренняя реализация
}

Публичные пакеты, которые могут использоваться другими подключаемыми модулями добавляем в список публичных. Это можно сделать в при помощи визуального редактора файла манифеста разрабатываемого подключаемого модуля (плагина), окрыв закладку «Runtime» и секцию «Exported Packages».

После рефакторинга проекта структура пакетов примет показанный на рис. 1. вид.



Непосредственно для обфускации кода воспользуемся плагином «obfuscate4e» который позволяет воспользоваться встроенным бесплатным обфускатором «ProGuard» либо подключить другой обфускатор. Для установки плагина просто обновим среду Eclipse с адреса:

http://obfuscate4e.partmaster.de/updates/

Для активизации плагина обфускации во время сборки нашего проекта, нужно в навигаторе проекта выбрать файл манифеста и вызвать контекстное меню нажатием правой кнопки мыши (см. рис. 2) после чего выбрать пункт меню «PDE Tools->Create customBuildCallbacks for Proguard».



В результате, в корень проекта будут добавлены файл customBuildCallbacks.xml который является настроечным для сборки при помощи ant и файл proguard.cfg для настройки параметров обфускации.

Дополнительно к этому, сам файл проекта будет настроен на компиляцию и обфускацию проекта. Причем, в файле настройки proguard.cfg сразу будут прописаны настройки для обфускации пакетов которые не включены в список публичных (в дальнейшем данный файл можно будет править самостоятельно).

Экспортируем проект и повторно анализируем код после декомпиляции. Первое, что бросается в глаза это то, что классы из пакета internal будут переименованы в файлы a, b, c ...

Во вторых, текст декомпилированных классов становится более трудночитаемым так как методы и имена переменных также переименованы, например:

final class d
  implements Runnable
{

  d(f f1, Display display, IWorkbench iworkbench)
  {
    a = display;
    b = iworkbench;
    super();
  }

  public final void run()
  {
    if(!a.isDisposed())
      b.close();
  }

  private final Display a;
  private final IWorkbench b;
}

Причем, чем больше внутренних классов в проекте, тем сложнее разобраться что за что отвечает и где символ «a» означает имя класса, а где название метода или переменной. А при очень большом количестве классов получаются наименования совпадающие с ключевыми словами языка java, например «do», «if», что очень сильно затрудняет анализ декомпилированного приложения. Дополнительной сложностью для взломщиков является взлом приложения, которое собиралось в операционной системе Linux. За счет того, что именна переменных и классов могут быть в разных регистрах, то классы с именами «a» и «A» просто невозможно декомпилировать в операционной системе Windows.

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

Рекомендуемые ресурсы:

Rambler's Top100 Рейтинг@Mail.ru