June 26, 2018

Отмычки для софта. Выбираем инструменты реверса и пентеста приложений для Android

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

Условно все инструменты анализа и реверса приложений (не только для Android) можно разделить на две группы:

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

В обеих группах есть утилиты и для самых маленьких (запустил — получил список уязвимостей), и для матерых пентестеров. Мы рассмотрим их все.

Статический анализ

Итак, для начала поговорим об инструментах статического анализа. Каждый пентестер должен иметь в своем арсенале хотя бы два из них. Это декомпилятор и дизассемблер.

Декомпилятор нужен, чтобы перегнать байт-код Dalvik обратно в код Java и с его помощью разобраться, как работает приложение. Дизассемблер транслирует байт-код в гораздо более низкоуровневый код Smali (местный ассемблер), в котором труднее разобраться, но зато он всегда корректен настолько, что его можно собрать обратно в приложение. Этой особенностью можно воспользоваться, например, чтобы внедрить в приложение собственный код, как мы это сделали во второй части статьи о взломе приложений для Android.

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

Jadx

Первый инструмент в нашем списке — декомпилятор Jadx. Это активно развиваемый открытый декомпилятор, который выдает достаточно неплохой код Java на выходе и даже имеет функцию деобфускации кода. Работать с ним просто: запускаешь Jadx-gui, с его помощью выбираешь APK-файл приложений и видишь иерархию пакетов и файлы с исходниками на Java.

Jadx может работать и в режиме командной строки. Например, следующая команда декомпилирует приложение example.apk и поместит полученный код Java в каталог out:

$ jadx -d out example.apk

Более того, Jadx может дополнительно сгенерировать файлы build.gradle, чтобы исходники можно было импортировать в Android Studio:

$ jadx -e -d out example.apk

Собрать приложение из них не получится, зато анализировать код будет гораздо удобнее.

Apktool

Второй инструмент, который должен обязательно быть на твоем диске, — это Apktool. Его назначение — разборка и сборка приложений. При этом термин «разборка» подразумевает дизассемблирование кода приложения в файлы формата Smali, а также декомпрессию ресурсов и файла AndroidManifest.xml.

С помощью Apktool можно разобрать приложение, проанализировать дизассемблерный код, внести в него правки и собрать обратно. О том, как это сделать, мы подробно писали в статье «Ломаем Android».

APKiD

Эта небольшая утилита понадобится тебе, когда ты заметишь, что Jadx не в состоянии декомпилировать приложение. В большинстве случаев это значит, что приложение было обфусцировано или упаковано с помощью специальных инструментов. APKiD позволяет узнать, какие конкретно инструменты были использованы, выяснить, было ли приложение пересобрано с помощью Apktool и используются ли в нем какие-то другие техники для защиты от дизассемблирования/декомпиляции и запуска в виртуальной машине.

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

  • anti_debug : Debug.isDebuggerConnected() check — проверка, подключен ли дебаггер с помощью метода isDebuggerConnected;
  • anti_vm : Build.MANUFACTURER check — проверка производителя смартфона, чтобы понять, что находишься в виртуальной машине.

Но есть одно неочевидное поле: compiler. Оно обычно содержит dx или dexlib. Dx — стандартный компилятор Android SDK, а dexlib — это библиотека сборки файлов DEX из Apktool. Проще говоря, если в поле compiler находится dexlib, значит, приложение было пересобрано с помощью Apktool или аналогичного инструмента.

Simplify

Что, если APKiD сообщает о применении обфускатора, а при попытке изучить код ты сталкиваешься с зашифрованными строками? В этом случае тебе нужен деобфускатор, который сможет сделать код более читаемым. Абсолютное большинство деобфускаторов, которые ты найдешь в интернете, умеют бороться только с одним или несколькими обфускаторами, зачастую устаревших версий.

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

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

$ java -jar simplify.jar -it 'org/cf/obfuscated' simplify/obfuscated-app.apk
До и после обработки Simplify

DeGuard

Simplify поможет, если приложение было пропущено через мощный обфускатор. Однако большинство программистов не обременяют себя применением чего-то более сложного, чем входящий в состав Android Studio ProGuard. А ProGuard — это оптимизатор, в котором функция обфускации появилась как побочный эффект. Единственное, чем он запутывает реверсера, — это измененные на бессмысленный набор букв имена классов, методов и полей.

Разобраться в обфусцированном с помощью ProGuard коде не так уж и сложно, но сложнее, чем в совсем не обфусцированном (в два раза сложнее, если верить исследованиям). Поэтому даже для ProGuard существуют деобфускаторы.

DeGuard — наиболее интересный из них. Это веб-сервис, созданный в Высшей технической школе Цюриха. С помощью нейросетей он способен восстановить (а точнее, предсказать) оригинальные имена пакетов, классов, методов и полей. Одна проблема: нередко деобфусцированный код запутывает еще больше, чем оригинал.

Bytecode Viewer

А это решение класса «все в одном». Bytecode Viewer сочетает в себе функции Jadx, Apktool и еще нескольких инструментов. Он умеет дизассемблировать приложения, декомпилировать их с помощью пяти различных движков декомпиляции (JD-Core, Procyon, CFR, Fernflower, Krakatau), расшифровывать строки с помощью трех движков дешифрования, компилировать приложение обратно из декомпилированного кода (с помощью Ranino Compiler) и даже искать зловредный код!

Многие реверсеры рекомендуют использовать именно этот инструмент для анализа приложений. Их аргумент в том, что любой другой декомпилятор (тот же Jadx или популярный JD-GUI) может сломаться об обфусцированный или специальным образом написанный код и просто не покажет его. В то же время Bytecode Viewer, благодаря наличию сразу пяти движков декомпиляции, имеет больше шансов декомпилировать такое приложение.

На самом же деле не все так радужно. Bytecode Viewer — это кое-как работающая сборная солянка из различных открытых инструментов. Да, в нем множество движков декомпиляции, но, похоже, автор перестал следить за своим произведением. Текущая версия Bytecode Viewer уже не может открыть большинство APK.

Скриншота не будет по причине неработоспособности инструмента.

QARK

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

Пользоваться QARK очень просто: запускаешь QarkMain.py, отвечаешь на несколько вопросов и получаешь отчет в формате HTML в каталоге quark/report.

Как и другие автоматизированные инструменты, QARK не может точно предсказать наличие уязвимости, он лишь высказывает предположение о ее существовании и дает реверсеру намек, в какую сторону следует копать. Поэтому не стоит надеяться, что ты просто установишь QARK и сразу начнешь стричь купоны на пентесте приложений. Без матчасти никуда.

Динамический анализ

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

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

Frida

Начнем с короля всех инструментов динамического анализа, трассировки и модификации приложений — с Frida. Это так называемый Dynamic Instrumentation Toolkit, набор инструментов, позволяющих на лету внедрять собственный код в другие приложения. Внедрив код, можно выполнить полную трассировку приложения, перехватить функции шифрования, записи файлов на диск и вообще сделать с приложением все что угодно.

В «Хакере» уже была подробная статья о Frida, поэтому не будем повторяться. Скажем только, что у Frida есть репозиторий с готовыми скриптами, которые могут тебе пригодиться:

  • fridantiroot — комплексный скрипт, позволяющий отключить проверки на root;
  • Universal Android SSL Pinning Bypass — обход SSL Pinning;
  • dereflector — скрипт Frida для дерефлексии Java-кода (превращения непрямых вызовов методов в прямые).
  • frida —codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f com.example.app

Objection

Frida — очень популярный инструмент. На его основе было создано множество более высокоуровневых утилит. Objection — одна из них. Она позволяет внедриться в приложение iOS или Android и провести анализ его приватного каталога, памяти, классов, методов, извлечь содержимое базы SQLite, обойти SSL-пиннинг.

Главное преимущество Objection в том, что она дает возможность «войти» в приватный каталог приложения точно так же, как это позволяет сделать устройство с root-доступом. Но в этом же ее недостаток: большинство задач, для которых предназначена Objection, легко решаются с помощью adb, команды sqlite (при наличии root) и общедоступных скриптов Frida.

Inspeckage

Inspeckage — еще один высокоуровневый инструмент динамического анализа приложений. У него огромное количество возможностей: он может получать информацию о полномочиях, активностях, контент-провайдерах и сервисах, умеет перехватывать обращения к SQLite, HTTP-серверам, файловой системе, буферу обмена, криптографическим функциям, запускать активности, подключаться к ContentProvider’aм и выполнять спуфинг местоположения.

Все это можно сделать, используя удобный веб-интерфейс. Но перед этим на смартфоне необходимо получить права root, а затем установить Xposed Framework (который как раз и позволяет Inspeckage выполнять перехват управления).

Drozer

На закуску у нас drozer — мощный инструмент для выполнения типичных задач пентеста приложений. Drozer позволяет получить информацию о приложении, запустить его активности, подключиться к ContentProvider’у, отправить сообщения сервису — в общем, сделать все, чтобы вытащить из приложения информацию или заставить его сделать то, что нам нужно.

Типичный воркфлоу drozer выглядит так. Сначала получаем информацию о приложении:

dz> run app.package.list
dz> run app.package.info -a com.example.app

Затем выводим список активностей и пробуем запустить их (возможно, некоторые из них не должны торчать наружу):

dz> run app.activity.info -a com.example.app
dz> run app.activity.start --component com.example.app <имя_активности>

Получаем информацию о ContentProvider’ах приложения:

dz> run app.provider.info -a com.example.app
dz> run scanner.provider.finduris -a com.example.app

Пробуем выудить из них информацию разными способами. Например, при помощи прямого запроса данных:

dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Password/ --vertical

Проверяем на наличие уязвимостей к инъекции и directory traversal:

dz> run scanner.provider.injection -a com.example.app
dz> run scanner.provider.traversal -a com.example.app

Получаем информацию о сервисах, пробуем запустить их, послать сообщения:

dz> run app.service.info -a com.example.app
dz> run app.service.start --action <действие> --component com.example.app <имя_компонента>
dz> run app.service.send com.example.app <имя_компонента> --msg <сообщение>

Одной строкой

  • Androl4b — образ виртуальной машины с набором перечисленных в статье инструментов;
  • AndroidRE — аналогичный по назначению образ Docker;
  • LazyDroid — скрипт для упрощения действий, связанных с анализом приложений, позволяет установить флаги отладки и бэкапа приложения, пересобрать и подписать приложение, выдернуть с устройства приложение, установленное с помощью Google Play, скопировать на комп приватный каталог приложения, внедрить гаджет Frida в APK;
  • AndroTickler — метаинструмент анализа Android-приложений, позволяющий получить исчерпывающую информацию о приложении, декомпилировать его, найти строки, URL, компоненты баз данных; плюс доступна интеграция с Frida.

Хай-теч вам в бок ✯