Реверсинг приложений под Android. Смотрим под капот
Мобильные устройства стали неотъемлемой частью нашей жизни. Без любимого гаджета мы лишаемся банковских приложений, госуслуг и других сервисов, без которых наша жизнь становится намного сложнее.
По этой причине мобильные приложения, являются лакомой целью для злоумышленников. Подселив вредонос на телефон жертвы можно получить доступ ко всем используемым приложениям. Конечно, есть защитные механизмы типа одноразовых паролей, но многие современные вредоносы умеют их обходить.
Поэтому специалистам по информационной безопасности необходимо понимать как работают приложения под Андроид и какие инструменты можно использовать для их реверсинга. В этой статье мы начнем рассматривать устройство приложений под Андроид и тот инструментарий, который нам понадобится.
Сразу замечу, что глубокое погружение в разработку под Андроид не является целью данной статьи. Мы будем говорить больше о реверсинге.
Внутри APK
Приложения в Андроид можно устанавливать из репозиториев, а можно «по-старинке» загружать установочные файлы и ставить их вручную, как это делается на «больших» компьютерах. В любом случае мы будем иметь дело с файлами формата APK. Формат APK - это, по сути, ZIP-файл. Для проверки вы можете переименовать расширение файла в .zip и использовать unzip, чтобы открыть и просмотреть его содержимое.
Давайте посмотрим, что находится внутри APK. Сразу замечу, что представленный список не является исчерпывающим.
AndroidManifest.xml – представляет основную информацию о программе системе
META-INF/ – здесь находится сертификат
classes.dex - байт-код Dalvik (регистровая виртуальная машина для выполнения программ, написанных на языке программирования Java) для приложения в формате файла DEX. Это Java (или Kotlin) код, который приложение будет запускать по умолчанию.
lib/ - Собственные библиотеки для приложения, по умолчанию, находятся здесь. В каталоге lib/ находятся каталоги, относящиеся к процессору. Например, armeabi, mips,
assets/ - Любые другие файлы, которые могут понадобиться приложению.
Сюда могут быть включены дополнительные собственные библиотеки или файлы DEX. Это может произойти, особенно когда авторы вредоносных программ хотят попытаться “скрыть” дополнительный код, native или Dalvik, не размещая его в местах по умолчанию.
Если говорить о языках программирования, используемых для написания приложений для Андроид, то большинство приложений написаны на Java. Kotlin также поддерживается и совместим с Java. Вместо того, чтобы Java-код запускался на Java Virtual Machine (JVM), как в настольных приложениях, в Android Java компилируется в формат байт-кода Dalvik Executable (DEX). Для более ранних версий Android байт-код был переведен виртуальной машиной Dalvik. Для более поздних версий Android используется Android Runtime (ART).
Таким образом, если разработчики пишут на Java, а код компилируется в байт-код DEX, для реверсинга, мы будем работать в противоположном направлении.
Ассемблер для Андроид
Для того, чтобы можно было работать с отреверсенным кодом приложением существует человеко-читаемая версия байт-кода Dalvik под названием Smali. Технически, Smali и baksmali - это названия инструментов (ассемблер и дизассемблер соответственно), но в Android мы часто используем термин “Smali” для обозначения инструкций.
Для лучшего понимания того, что из себя представляет код на Samli рассмотрим пример кода для Hello World на Java:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Код на Smali будет иметь следующий вид:
.method public static printHelloWorld()V
.registers 2
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World"
invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method
В рамках данной статьи мы не будем подробно рассматривать использование инструкций Smali. Желающие могут прочитать про них в статье https://habr.com/ru/articles/495024/.
Однако, чаще всего при реверс-инжиниринге Android-приложений вам не нужно будет работать непосредственно со Smali. Большинство приложений можно поднять на еще более высокий уровень, декомпилировав Java. Как и все инструменты, Java-декомпиляторы могут содержать ошибки и полученный в результате декомпиляции код может быть не совсем верным. Поэтому, если код не внушает доверие, лучше вручную попробовать понять что делает та или иная команда.
Для реверсинга вы можете воспользоваться инструментом baksmali (дизассемблер), который доступен по адресу https://github.com/JesusFreke/smali/wiki. Инструмент small позволит вам собрать small обратно в DEX.
Инструменты
Прежде, чем продолжить погружение в реверсинг предлагаю поставить на загрузку образ виртуалки, содержащей необходимые инструменты:
Виртуальная Машина представляет собой 64-разрядный образ Ubuntu 18.04. Имя пользователя - Android App RE, а пароль - android. На виртуальной машине установлены следующие инструменты:
jadx - декомпилятор Android. Мы будем загружать APK-файлы в jadx, и затем анализировать байт-код DEX с помощью jadx.
Ghidra - инструмент хорошо знакомый всем реверсерам. В разбираемых далее примерах мы используем функциональность дизассемблера/декомпилятора ARM для статического анализа кода.
Пока загружается образ виртуалки, посмотрим основные моменты, связанные с работой Android приложений.
Ищем вход
Все, кто хотя бы немного знаком с реверсингом знает, что один из самых важных моментов в реверс-инжиниринге – это, знание того, с чего начать анализ кода. Когда вы видите набор команд то мягко говоря не просто понять что же делает этот код. И поиск точки входа для выполнения кода являются важной частью этого анализа, так как именно с начальной точки лучше всего начинать анализ любого кода.
Действия при запуске - это то, что обычно считают точкой входа в приложение для Android. Действие запуска - это действие, которое запускается, когда пользователь нажимает на значок приложения. Вы можете определить действие запуска, просмотрев манифест приложения. Действия выполняемые при запуске будут представлены в блоках MAIN и LAUNCHER.
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
При этом, имейте в виду, что не каждое приложение будет выполнять действия при запуске, особенно если это приложение без пользовательского интерфейса. Примерами приложений без пользовательского интерфейса (и, следовательно, без действий при запуске) являются предустановленные приложения, которые выполняют службы в фоновом режиме, такие как голосовая почта.
Службы
Службы работают в фоновом режиме без пользовательского интерфейса. Существует множество способов, которыми они могут быть запущены и, таким образом, являются точкой входа для приложений. При вызове API startService для запуска службы выполняется метод OnStart в Службе.
Широковещательные приемники
Широковещательные передачи можно рассматривать как систему обмена сообщениями, а получателей широковещательных сообщений - как слушателей. Если приложение зарегистрировало получателя для определенной широковещательной передачи, код в этом получателе выполняется, когда система отправляет широковещательную передачу. Приложение может зарегистрировать получателя двумя способами: в манифесте приложения или динамически зарегистрироваться в коде приложения с помощью вызова API registerReceiver().
Когда отправляются конкретные широковещательные сообщения, для которых зарегистрирован получатель, выполняется функция onReceive в классе BroadcastReceiver.
Экспортированные компоненты
Службы и действия также могут быть “экспортированы”, что позволяет другим процессам на устройстве запускать службу или действие. Компоненты экспортируются путем установки элемента в манифесте. По умолчанию android:exported="false", если для этого элемента в манифесте не задано значение true или если для действия или службы не определены фильтры намерений.
<service android:name=".ExampleExportedService" android:exported="true"/>
<activity android:name=".ExampleExportedActivity" android:exported="true"/>
Что же теории на сегодня будет достаточно и сейчас самое время перейти к практике. Надеюсь вы уже скачали и загрузили виртуальную машину.
Практика с Jadx
ВМ уже содержит каталог Samples, в котором есть необходимые учебные примеры. Начнем мы с файла ~/samples/ThaiCamera.apk. Будем предполагать, что этот артефакт может быть связан с мошенничеством с использованием сильно-платных SMS-сообщений, что означает отправку SMS-сообщений на номер телефона премиум-класса без раскрытия информации и согласия пользователя.
В этом задании мы посмотрим, как работает Jadx и что из себя представляет содержимое APK-файла. Итак, запустите jadx, открыв терминал на виртуальной машине и выполнив команду jadx-gui в терминале. Когда вы откроете приложение в jadx, вы увидите, что под заголовком "Source Code" указаны пакеты (пространства имен для классов Java), включенные в приложение.
Посмотрим содержимое вкладки “Resources”. Наиболее интересные здесь - манифест (AndroidManifest.xml), classes.dex (содержит байт-код DEX, который декомпилирован на вкладке “Source Code”) и папка assets/, в которой содержатся любые другие файлы, которые могут понадобиться APK для запуска.
Можно конечно начать поиск вручную, например с файла манифеста, но так как у нас уже есть подозрения в том, что этот файл выполняет какие-то сомнительные манипуляции с отправкой Sms, то проще всего выбрать Navigation, Text Search и далее напишем просто Sms.
Сразу видим множество интересных вызовов. В качестве примера посмотрим, что за обращение к внешнему ресурсу используется. Для этого просто нажмем на данную строку и провалимся в соответствующий фрагмент кода.
Дальше уже можно более детально изучать содержимое кода, но этим мы займемся уже в следующей статье.
Заключение
Сегодня мы познакомились с основами реверсинга приложений под Android. Пока мы только начали погружаться в эту тему, но в следующих статьях мы продолжим рассматривать вопросы реверсинга уже более глубоко.
Больше про реверсинг и другие методы обеспечения безопасности эксперты OTUS рассказывают в рамках практических онлайн-курсов. С полным каталогом курсов можно ознакомиться по ссылке.