Обновлено 2015-09-17: исправлены ссылки на программы
Приложения для андроида распространяются в виде файлов с расширением apk, внутри такого файла лежат бинарные и текстовые ресурсы приложения, манифест со всякой технической информацией о пакете, а также скомпилированный код собственно приложения. И в какой-то момент неизбежно возникает желание расковырять чужой пакет, чтобы вытащить оттуда картинку, например, или посмотреть, как устроены макеты интерфейсов.
Вот этим мы и займёмся. Традиционно здесь всё рассказывается в контексте линукса, с остальными операционками разбирайтесь сами, хотя принцип ровно такой же.
Предварительная подготовка¶
Нам понадобится телефон с андроидом, дата-кабель к нему, настроенный для работы с ADB компьютер1, установленный Android SDK (каталоги tools
и platform-tools
должны быть вынесены в переменную окружения PATH
).
Также на телефоне необходимо разрешить отладку через USB.
Ещё необходимо добавить какой-нибудь каталог, в который вы можете писать, в переменную окружения $PATH, у меня туда добавлен каталог ~/bin
.
Получение apk-файла приложения¶
Есть несколько способов добыть файл с пакетом приложения:
- скачать с интернета, на всяких форумах часто выкладывают пакеты;
- скачать с официально сайта приложения, такое тоже бывает, да;
- вытащить из собственного телефона, куда приложение было установлено с маркета.
Первые два способа тривиальны, о них не будем рассказывать, а вот третий достоин внимания. Подключаем телефон кабелем к компьютеру, проверяем, что девайс видится командой adb
:
% adb devices
List of devices attached
3731276A498700EC device
Допустим, нас интересует приложение Google+, очевидно, что где-то в названии приложения должно быть слово plus
, ищем:
% adb shell pm list packages -f plus
package:/data/app/com.google.android.apps.plus-1.apk=com.google.android.apps.plus
package:/data/app/org.geometerplus.zlibrary.ui.android-1.apk=org.geometerplus.zlibrary.ui.android
Что мы только что сделали? Мы выполнили команду на стороне девайса (adb shell
), команда называется pm
(т.е. package manager), опция команды list packages
говорит сама за себя, опция -f
включает отображение связанных с пакетом файлов; а plus
— это фильтр.
Видим, что интересующее нас приложение лежит в файле /data/app/com.google.android.apps.plus-1.apk
, вытаскиваем его на компьютер:
% adb pull /data/app/com.google.android.apps.plus-1.apk .
3132 KB/s (8913253 bytes in 2.778s)
Разбор apk-файла на части¶
APK-файл фактически является обычным ZIP-архивом, внутри которого лежат скомпилированные исходники приложения, ресурсы и манифест. Вы можете в этом сами убедиться:
% unzip -l com.google.android.apps.plus-1.apk
Archive: com.google.android.apps.plus-1.apk
Length Date Time Name
--------- ---------- ----- ----
97360 2008-08-21 17:13 META-INF/MANIFEST.MF
97402 2008-08-21 17:13 META-INF/CERT.SF
1580 2008-08-21 17:13 META-INF/CERT.RSA
39212 2008-08-21 17:13 AndroidManifest.xml
3162 2008-08-21 17:13 assets/licenses.html
5293140 2008-08-21 17:13 classes.dex
7608988 2008-08-21 17:13 lib/armeabi/libgcomm_jni.so
... тут пропущено много строчек
2493944 2008-08-21 17:13 resources.arsc
--------- -------
16786021 1042 files
Однако просто распаковать и дальше ковыряться в этом всём, к сожалению, не получится: эти файлы там лежат в бинарном оптимизированном для использования на девайсе формате, их нужно сначала декодировать в пристойный вид.
Для этого есть замечательный инструмент android-apktool, полная инструкция по установке описана на официальном сайте. Нас интересует версия 2.X, скачиваем jar-файл в каталог ~/bin
, туда же скачиваем скрипт-обёртку, примерно так:
cd ~/bin/
wget https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.0.1.jar
wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool
chmod +x apktool
Проверяем в терминале, что команда apktool
работает, просто набираем и смотрим. Если выдаётся ошибка, фиксим, например, пермиссии на файл. Когда всё заработает, можно приступать к декодированию, всё просто:
% apktool d com.google.android.apps.plus-1.apk gplus
I: Baksmaling...
I: Loading resource table...
I: Loaded.
I: Loading resource table from file: /home/USER/apktool/framework/1.apk
I: Loaded.
I: Decoding file-resources...
I: Decoding values*/* XMLs...
I: Done.
I: Copying assets and libs...
После завершения процесса внутри каталога gplus
будут лежать декодированные (в некоторой степени) внутренности пакета. К примеру, там уже можно смотреть в нормальном виде xml-файлы (макеты интерфейса или манифест). Там даже можно увидеть слегка декодированные исходники приложения, но не в виде java-кода, а в виде smali-файлов, об этом формате подробнее можно тут прочитать, при желании их можно даже редактировать и затем собрать назад в apk-пакет (это также можно сделать при помощи apktool
).
Дизассемблирование до java-кода¶
Следующий шаг — попытаться добраться до близкого к оригинальному java-кода приложения. В этом нам поможет программа dex2jar, качаем с сайта проекта архив с программой (файл вида dex2jar-0.0.9.8.tar.gz), она тоже написана на java, внутри каталог с кучей файлов, из которых нам понадобится каталог lib
(скопируем его целиком в ~/bin
):
$ cp -r ./lib ~/bin/
и dex2jar.sh
, скопируем его туда же в ~/bin
. Запускаем на примере нашего пакета (на большом пакете программа может долго работать):
% dex2jar.sh com.google.android.apps.plus-1.apk
dex2jar version: translator-0.0.9.8
dex2jar com.google.android.apps.plus-1.apk -> com.google.android.apps.plus-1_dex2jar.jar
Done.
После выполнения получим в этом же каталоге jar-файл (в нашем случае — com.google.android.apps.plus-1_dex2jar.jar
).
Это самый обычный java jar archive, содержащий обычные class-файлы со скомпилированным java-кодом.
Декомпиляция class-файлов в java-файлы¶
Финальный этап — это получение более-менее читабельного java-кода из class-файлов с байткодом. Эта задача частично решается программой из предыдущего раздела: скопируем в каталог ~/bin
скрипт d2j-jar2jasmin.sh
. Результатом работы скрипта является каталог с файлами в формате jasmin, что, однако, вовсе не java-код, но тоже может оказаться полезным для анализа:
% d2j-jar2jasmin.sh -o res com.google.android.apps.plus-1_dex2jar.jar
disassemble com.google.android.apps.plus-1_dex2jar.jar -> res
Но можно получить и java-код! Для этого можно попробовать воспользоваться вот этим дизассемблером. Не факт, что сработает на вашем пакете, плюс не гарантируется извлечение компилируемого кода, но какие-то данные вы всё же получите.
Что осталось за кадром¶
Я не рассматриваю вопрос преобразования odex-файлов в dex-файлы. Об этом можно самому прочитать вот тут, например.
Аналогично вопрос обратной сборки файлов в apk-пакет тоже не рассматривается. Так же как и подписывание/выравнивание apk-пакета.
Ссылки¶
-
особенности настройки линукс-машины для работы с телефоном по дата-кабелю раскрываются в соответствующей статье на сайте developer.android.com ↩
Тут со своим кодом разобраться бы, а потом только за чужие файлы браться. Я что в ЯВЕ написал более двух месяцев назад, если код более 1000 строк уже с переводчиком должен смотреть.
Да чё вы так всё усложнили?! Тут проще чем написать слово "молоко"! Просто поменяйте расширение "apk" в "rar". И всё!
P.S. Написано на Си.)
Читай статью повнимательней: