Пользователь
0,0
рейтинг
12 февраля 2014 в 13:43

Разработка → Простой способ модификации Android приложения из песочницы

Бывает после релиза приложения его исходники куда-то деваются. Правда ведь, такое постоянно случается? И ничего не остается кроме как декомпилировать его и подправить несколько сотен строк кода и все это нужно сделать максимально быстро.

Вот и у меня появилась задача модифицировать приложение имея всего лишь его apk. И те, кто занимался декомпиляцией приложений знают насколько тяжело его потом скомпилировать.

Декомпиляция


Для Android'а существуют следующие утилиты:
  • ApkTool для декомпиляции ресурсов.
  • Dex2Jar для преобразования dex в jar.
  • JD-GUI для получения исходников из jar.
  • еще рекомендую JAD, некоторые места лучше декомпилирует чем JD-GUI.

Информации по их использованию в интернете достаточно.

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

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

Переопределение классов


Итак, jar это библиотека, так почему бы просто не подключить ее к новому проекту? Кидаем ее в папку libs, наследуемся от главной активити и компилируем. Все работает, главное чтоб не совпадали имена классов, поэтому названия пакетов должно отличаться иначе как минимум совпадут сгенерированные BuildConfig и R.

Таким способом можно отнаследоваться от Activity, Service, BroadcastReceiver и, возможно, некоторых других классов объявляемых в манифесте, так же в манифесте нужно будет указать новые имена классов, иначе они не будут использоваться.

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

Замена классов


Разархивировав jar библиотеку получим class файлы, это скомпилированные классы, заметим, что при сборке проекта в папке bin/classes лежат те же class файлы, а что если подсунуть туда файлы из библиотеки…

Не все так просто, для начала нужно скомпилировать проект. Чтобы использовать классы исходного приложения нужно его как-то присоединить к проекту, но при этом не экспортировать. Делается это просто: из папки libs Эклипс сам экспортирует библиотеки, поэтому перемещаем jar библиотеку в папку lib и подключаем к проекту, в Эклипсе это Project->Preferences->Java Build Path->Libraries->Add Jars… далее во вкладке Order and Export нужно убедиться, что не установлен чекбокс, потому что экспортировать библиотеку нам не нужно, все будет в class файлах.

Теперь берем какой-нибудь класс из декомпилированных исходников приложения, исправляем в нем ошибки компиляции, добавляем, например, показ диалога, чтоб убедиться, что используется именно новый класс. Далее очищаем проект, в Эклипсе это Project->Clean, копируем class файлы в папку bin/classes, собираем проект и все работает!

При следующих сборках проекта нет необходимости его очищать, так что использовать такой способ достаточно удобно. Для облегчения исправления ошибок после декомпиляции я использовал исходники полученные из JD-GUI и JAD, обычно этого было достаточно.

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

Заключение


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

С большой вероятностью не получится скрыть все следы от оригинального приложения, названия необфусцированных классов таких как Activity и Service, а так же названия их пакетов сохранятся и будут доступны после декомпиляции модифицированного приложения, но для пиратских версий это не проблема, из-за чего стоит защищать приложение, способы защиты аналогичны другим способам защиты от изменения кода.

Обновление классов в jar — идея замены классов пришла из этой возможности для jar библиотеки.
Андрей @uxgen
карма
3,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (14)

  • +2
    ключевое слово final

    для того, чтобы снять пару модификаторов, необязательно декомпилировать — можно поправить «на живую» прямо в байт-коде.
  • +2
    Apktool умеет не только декомпилировать в smali, но и обратно собирать apk. А smali достаточно удобен для быстрых правок.
  • +4
    Бывает после релиза приложения его исходники куда-то деваются.

    Никогда такого не было. Может быть потому-что пользуюсь репозиторием для хранения исходников?
    Мне вобще сложно представить как код можно не коммитить.

    За статью спасибо. Интересно было почитать о проблемах.
    • +2
      Никогда такого не было. Может быть потому-что пользуюсь репозиторием для хранения исходников?
      Мне вобще сложно представить как код можно не коммитить.

      Мне кажется — имелся в виду намек на необходимость декомпиляции «не совсем своего» приложения. Хотя, конечно, я могу и ошибаться…
      • 0
        Мне кажется — имелся в виду намек на необходимость декомпиляции «не совсем своего» приложения.

        Да, нужно было немного переделать старое приложение написанное другим программистом, а исходников не было.
  • 0
    Интересно как быть с подписанными приложениями?
    • 0
      Вроде бы все приложения подписываются.
    • 0
      Переподписать своей подписью
      • 0
        Если она есть. Как пишет автор, исходники потерялись и не факт что keystore остался. А вот можно ли приложение (пусть даже не свое) изменить, подписать и выложить скажем в play.google.com, чтобы пользователи могли без проблем обновиться?
        • 0
          При потере ключа обновление сделать нельзя. Однако, можно поставить «рядом» свою версию с другим package name
  • 0
    Мне интересно… Сколько уже лет сообщество пользуется глючной jd-gui и терпит все её баги с ветвлениями и циклами. Для open-source программы — вообще немыслимая ситуация. Хоть бери и сам исправляй.
  • +1
    В качестве декомпилятора может быть полезен dirtyJOE — Java Overall Editor is a complex editor and viewer for compiled java binaries (.class files).

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.