Защита кода приложения Android. Когда хотели как лучше, а вышло не очень

ac1f39870cb27438fd1886a5bba3fc97.png

Эта статья — оригинальная, а не копипаст и не машинный перевод. При копировании прошу ссылаться.

В статье просто расскажу пару случаев из практики анализа защиты приложений Android. Имена и место событий изменены. Любые совпадения — случайность.

Случай первый.
Когда Dexprotector совсем не Protector.

Объект исследования — мобильное приложение для Android крупного европейского on-line банка. До какой-то версии в приложении применялись отдельные практики защиты: проверка подписи, проверка на эмулятор и root и TLS pinning. Но вот, однажды, банк объявил, что выпускает новую версию приложения, в которой реализованы, в том числе и наиболее современные механизмы защиты.
Есть люди, и я к ним себя отношу, которые не верят на слово, а хотят, так сказать, увидеть лично. Тем более, что банк в принудительном порядке заставил обновить приложение.
Уже вскрытие файла AndroidManifest.xml показало, что техническому руководству банка надоело править каждый механизм защиты отдельно, и они решили применить интегрированное решение — Dexprotector (https://licelus.com/products/dexprotector) от Licel.

В файле AndroidManifest.xml в разделе обычные для этого приложения параметры:

android:appComponentFactory="androidx.core.app.CoreComponentFactory"
android:name="com.bankx.Application"

превратились в:

android:appComponentFactory="**com.bankx.ProtectedAppComponentFactory**"
android:name="**com.bankx.ProtectedApplication**" 

Следующим подтверждением применения Dexprotector стало наличие на борту библиотеки dexprotector.so

Dexprotector -довольно мощная и платная штука, сочетающая в себе практически все наработки в области защиты приложений Android. Одна беда у них — уж очень они любят слово Protected и основной функционал размещают в объекте класса Application. Поэтому первым шагом к избавлению от Dexprotctor является полное его исключение из приложения. То есть, мы возвращаем AndroidManifest.xml в его прежний вид. Далее ищем где еще в файлах, в именах которых нет слова Protected, используется объект com.bankx.ProtectedApplication.
В нашем случае нашлось несколько файлов, содержащих одну и ту же строку:

invoke-static {v0, p1}, Lcom/bankx/ProtectedApplication;→Gpwweokk(Ljava/lang/Object;Ljava/lang/String;)Ljava/io/InputStream;

Можно разбираться что это и зачем, но мы поступаем проще — берем тот же файл из приложения версии «до Dexprotector» и сравниваем содержимое. Если ничего, кроме этой строки не изменилось, то просто восстанавливаем содержимое до первоначального состояния.

Прбуем запустить приложение, и улетаем в ошибку «NoClassDefFoundError» . Ожидаемо. Почему? Потому что Dexprotector может «скрывать» некоторые классы, восстанавливая их при запуске. Но у нас Dexprotector теперь не работает — мы его выключили. Ну, а вдруг эти классы не изменились с крайней чистой версии приложения? Давайте просто их добавим.
Сказано — сделано. И, о чудо, новейшая версия приложения прекрасно запускается на эмуляторе из переподписанного файла, который теперь можно изменять по своему усмотрению. Приложение банка.
То есть смуглые разработчики из далекой Индии убрали все отдельные проверки, которые кстати тоже обходились замечательно, и заменили их на Dexprotector в полной уверенности, что теперь то все под контролем.
А что они сделали не так — подумайте сами, уважаемые читатели этой статьи.

Случай второй.
Всего один байт.

Объект исследования — мобильное приложение для Android крупного китайского marketplace. Не работает на эмуляторе и переподписанным. Несколько попыток — и наши китайские товарищи блокируют аккаунт.
Приложение выпускается только для одного варианта архитектуры — arm64-v8a. То есть еще и не на всех эмуляторах можно запустить.
Ладно, посмотрим что у него под капотом. Идем последовательно с момента запуска, распутываем клубок кода и упираемся в вызов библиотеки libxxbitmapkit.so. «К чему бы такой bitmap?», спросил бы себя старик Синицкий. Где-то свернули не туда?
Возвращаемся, перепроверяем, и опять приходим к libxxbitmapkit.so.
Ну хорошо. Давайте посмотрим на эту библиотеку под микроскопом фирмы ИДА.
«Ух ты!, Вот ведь…, Ё-маё!»
Заглянем в экспорт, находим функцию OnLoad (), видим, что после вызова пары подпрограмм алгоритм разделяется. Меняем условие на обратное и все)). Приложение прекрасно себя чувствует на эмуляторе, и когда в нем что то меняют, исключительно в познавательных целях.
Просто, как один байт поменять!

Заключение.
Как сказал один афроамериканец в голивудском фильме, по версии преводчика:» Не важно, что ты стоишь рядом с машиной. Важно как ты ей управляешь». И ведь не поспоришь
.
В своей статье я намеренно не стал изменять название Dexprotector. Это не реклама и не анти-реклама. Dexprotector — это действительно отличный инструмент. И у него есть конфигурационный файл, позволяющий сделать очень тонкую настройку. Товарищи же из Поднебесной, которые трудились над приложением долгих и днем и ночью, просто создали единую точку отказа в системе безопасности размером в один байт.

Это я все к чему? К тому, что лень одного человека — двигатель прогресса для другого).

P.S.
Я за чистоту Русского Языка, и терпеть не могу, когда иностранные слова используют в кириллице, типа «кейс» или «сниппет» и вставляют их в устную речь, даже когда общаются с широкой и разнородной аудиторией, искажая Великий и Могучий. Считаю это признаком недалекости ума (Личное мнение автора статьи).

© Habrahabr.ru