Эмуляция мобильных банковских приложений: Android App Cloning и патчинг безопасности

Good Carder

Professional
Messages
753
Reaction score
493
Points
63

Введение: почему мобильные приложения стали крепостью, которую штурмуют изнутри​

Современное мобильное банковское приложение — это не просто удобный интерфейс. Это многослойная крепость: обфускация кода, проверка целостности DEX, детекция root, эмулятора и отладчика, SSL‑пиннинг и сотни других механизмов. Задача исследователя — не взломать крепость снаружи, а убедить её, что вы свой. Для этого надо не только понимать защиту, но и уметь её обходить, модифицируя само приложение или перехватывая его вызовы на лету.

Часть 1. Распаковка APK и первичный анализ​

1.1. APKTool: декодирование ресурсов и smali-кода​

Первый шаг в исследовании любого Android‑приложения — распаковка APK. APKTool работает на более низком уровне, чем декомпиляторы: он извлекает все ресурсы, преобразует бинарный XML в читаемый формат и конвертирует DEX‑файлы в smali — ассемблер для виртуальной машины Dalvik. Это позволяет не только смотреть, но и модифицировать код приложения с последующей пересборкой.

Code:
# Базовая команда распаковки
apktool d target.apk -o target_unpacked/

# Пересборка после модификации
apktool b target_unpacked/ -o target_modified.apk

1.2. JADX: декомпиляция в читаемый Java/Kotlin‑код​

Если APKTool даёт ассемблер, то JADX (особенно JADX‑GUI) декомпилирует DEX прямо в Java/Kotlin, что намного удобнее для понимания бизнес‑логики.

Практический подход:
  • Первичная разведка через JADX — быстрый анализ структуры пакетов, поиск ключевых классов, строковых констант (URL, API, флаги).
  • Глубокий анализ через APKTool — если JADX не справляется (обфускация, кастомные загрузчики), распаковываем APKTool и изучаем smali.

1.3. Обнаружение обфускации и первых сигнатур защиты​

После распаковки смотрим на структуру:
  • Несколько DEX‑файлов (classes2.dex, classes3.dex) — возможно, часть логики вынесена в отдельные модули.
  • Сильно обфусцированные имена классов (a.a, b.b.c) — признак работы ProGuard.
  • Нативные библиотеки (lib/armeabi-v7a/*.so) — критическая логика (криптография, проверки целостности) часто вынесена в C/C++ код.

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

Часть 2. Обфускация и первый барьер: ProGuard / DexGuard​

2.1. ProGuard — стандарт обфускации Android​

ProGuard — open‑source инструмент, встроенный в Android Studio. Он делает четыре вещи: сжатие, оптимизацию, обфускацию и предпроверку кода. Обфускация переименовывает классы, методы и поля в короткие нечитаемые имена (a.a, b.b), что затрудняет понимание логики.

2.2. DexGuard — коммерческий зверь​

DexGuard — платное, более агрессивное решение. В дополнение к стандартной обфускации добавляет шифрование строк, инъекцию обфусцированного кода в ресурсы, вызовы через рефлексию и интеграцию с native‑библиотеками.

2.3. Методы обхода обфускации​

  • Анализ через mapping‑файл — если приложение ваше или вы нашли mapping.txt (часто в утечках), ProGuard предлагает ReTrace для восстановления трассировок стека.
  • Динамический анализ — обфускация затрудняет статический анализ, но не скрывает логику во время выполнения. Хуки в ключевые API показывают реальные значения параметров, независимо от имён.
  • Работа с зашифрованными строками — DexGuard может хранить чувствительные строки в зашифрованном виде с расшифровкой в рантайме. Зашифрованные строки расшифровываются в момент использования. Хук на точку расшифровки покажет исходную строку.

2.4. Практический пример перехвата логина​

Предположим, приложение вызывает a.b.c.x(str) для проверки пароля. Метод обфусцирован, но через динамический анализ (Frida) выясняем, что он отправляет POST‑запрос на https://api.bank.com/login. После декомпиляции вы ищете строку, где этот URL инициализируется — часто это точка входа для дальнейшего анализа.

Часть 3. Динамический анализ: Frida и Objection​

Статического анализа недостаточно — особенно когда обфускация и анти‑tamper проверки срабатывают только в рантайме. Здесь на помощь приходит инструментация в реальном времени.

3.1. Frida: швейцарский нож динамической инструментации​

Frida внедряет движок V8 (Chrome) в целевой процесс и позволяет выполнять произвольный JavaScript‑код прямо в памяти приложения для перехвата, модификации и анализа вызовов. Она работает на rooted‑устройствах через frida-server (фоновый процесс, который принимает команды от вашего компьютера), либо на нерутированных — через внедрение frida-gadget в APK.

Установка на устройство:
Bash:
# Скачивание frida-server для вашей архитектуры и запуск
adb push frida-server /data/local/tmp/
adb shell chmod +x /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

Базовый скрипт для перехвата вызовов:
JavaScript:
Java.perform(function() {
    var MainActivity = Java.use("com.bank.MainActivity");
    
    // Перехват метода login
    MainActivity.login.implementation = function(username, password) {
        console.log("[*] Login called with: " + username + ", " + password);
        
        // Модифицируем ответ
        var result = this.login(username, password);
        console.log("[*] Result: " + result);
        
        return true; // всегда успешно
    };
});

Запуск скрипта:
Bash:
frida -U com.bank.app -l hook_login.js

3.2. Objection: runtime exploration toolkit​

Objection — это обёртка над Frida, которая автоматизирует типовые задачи и предоставляет интерактивную среду для исследования приложения в рантайме.

Objection позволяет:
  • Исследовать загруженные классы — просматривать иерархию, методы, поля прямо в рантайме.
  • Обходить SSL‑пиннинг одной командой: android sslpinning disable (стандартные реализации).
  • Обходить root‑detection: android root disable.

Патчинг APK для нерутированных устройств:
Bash:
objection patchapk --source original.apk --target patched.apk --use-aapt2
Эта команда внедряет frida-gadget в APK, подписывает его новым ключом (необходима переустановка). После этого Objection может подключаться к приложению без root и без отдельного frida-server на устройстве.

3.3. Продвинутые скрипты для обхода детекции​

Когда стандартных команд недостаточно, пишутся кастомные Frida‑скрипты. Они:
  • Идентифицируют методы детекции через статический или динамический анализ.
  • Ху́кают нативные проверки — если детекция реализована в C/C++, стандартные Java‑хуки не помогут. Нужно хукать функции на уровне native‑кода.
  • Инжектируются раньше всех — чтобы перехватить проверки на старте приложения.

Пример комплексного Frida‑скрипта, обходящего root, эмулятор и SSL‑пиннинг одновременно, предоставляет репозиторий Frida Universal Android Hardening Bypass.

Часть 4. Маскировка окружения: Magisk и LSPosed​

4.1. Magisk — системный root​

Magisk вносит изменения в boot‑раздел, не затрагивая системный. Это позволяет приложению «думать», что система не изменена, даже если у вас есть root. После установки Magisk настройка включает:
  • Сокрытие приложения Magisk — упаковка со случайным именем пакета.
  • Включение Zygisk — механизм для запуска кода сокрытия прямо в процессе Zygote.
  • Очистка DenyList — список приложений, от которых нужно скрыть root.
  • Отключение принудительного применения DenyList (Enforce DenyList) — чтобы не ломать модули.

4.2. LSPosed — Xposed Framework нового поколения​

LSPosed позволяет перехватывать и изменять поведение приложений на Java‑уровне. Установка — через ZIP‑модуль в Magisk.

BypassRootCheckPro — модуль для LSPosed, который перехватывает не только Java‑проверки root, но и native‑вызовы (C/C++), работая там, где обычные методы бессильны.

4.3. Другие модули для маскировки​

  • TrickyStore — помогает обходить проверки Magisk через анализ ключей и сертификатов.
  • DeviceSpoofLab — подмена идентификаторов устройства (IMEI, Android ID, MAC‑адреса).
  • Shamiko — модуль для более глубокого сокрытия следов Magisk.

4.4. Комбинация для total invisibility​

Для максимальной маскировки применяется стек: LSPosed (для Java‑хуков) → Magisk + Shamiko (для сокрытия root) → DeviceSpoofLab (для подмены идентификаторов) → BypassRootCheckPro (перехват специфических банковских проверок).

Часть 5. Механизмы Anti‑Tamper и их обход​

5.1. Проверка целостности DEX​

Приложение вычисляет хэш (контрольную сумму) своих DEX‑файлов при каждом запуске и сверяет с «эталонным» значением, зашитым в коде или native‑библиотеке. Подмена классов после распаковки APKTool изменит хэш, и проверка не пройдёт.

Методы обхода:
  • Патчинг самой проверки — найти в коде место, где вычисляется хэш, и заменить его на всегда возвращающий «успех».
  • Подмена файлов уже после проверки — загрузить патч после того, как проверка целостности завершилась.
  • Обход через Frida — перехватить вызов, возвращающий true независимо от реального хэша.

5.2. Проверка подписи приложения​

Приложение сравнивает свою подпись с эталонной через PackageManager.getPackageInfo(). Если подпись не совпадает — приложение отказывается работать.

Обход: пропатчить проверку через Frida, перехватить вызов getPackageInfo и вернуть эталонную подпись вместо реальной. Альтернативно — переподписать APK тем же ключом, что и оригинал (если он известен). Но чаще патчится именно проверка.

5.3. Детекция отладчика​

android.os.Debug.isDebuggerConnected() возвращает true, если к приложению подключён отладчик (например, Android Studio или jdb). Многие банковские приложения проверяют этот флаг и при положительном результате аварийно завершаются.

Обход: перехват Frida — замена возвращаемого значения на false.

5.4. Native‑уровень: проверки в C/C++​

Самые серьёзные проверки вынесены в native‑библиотеки (.so). Причина — их сложнее анализировать и модифицировать. Такие проверки могут включать:
  • ptrace — проверка, не присоединён ли отладчик через системный вызов ptrace.
  • /proc/self/maps — сканирование на наличие frida, xposed, substrate.
  • Сканирование процессов — на наличие frida-server, gdb, android_server.
  • Проверка системных свойств — ro.kernel.qemu (эмулятор), ro.debuggable (отладочная сборка) и др.

Эти проверки остаются незамеченными для Java‑хуков.

Обход native‑проверок:
  • Хуки на уровне native‑кода — с помощью Frida на C‑API (Interceptor.attach на символы в .so).
  • Патчинг самих .so‑библиотек — через IDA Pro или Ghidra: находим функцию проверки, модифицируем инструкции возврата и пересобираем APK.
  • Подмена значений в /proc и системных свойствах — с помощью модулей Magisk.

Часть 6. Итоговый чек‑лист для исследования защищённого приложения​

  1. Распаковка и статический анализ. Декомпиляция через JADX‑GUI; при сильной обфускации — распаковка APKTool и изучение smali. Выявление очевидных проверок root/эмулятора, поиск URL и API‑эндпоинтов.
  2. Настройка окружения. Рутированное устройство с Magisk + Shamiko + LSPosed. Отключение Enforce DenyList, включение Zygisk. Установка модулей BypassRootCheckPro и DeviceSpoofLab.
  3. Динамический анализ через Frida/Objection. Обход SSL‑пиннинга (android sslpinning disable). Обход root‑детекции (android root disable). Написание кастомных скриптов, если стандартные методы не работают.
  4. Работа с native‑проверками. Выявление native‑функций через анализ .so в IDA/Ghidra. Написание Frida‑скриптов для хука native‑кода. При необходимости — патчинг .so и пересборка APK.
  5. Bypass anti‑tamper. Обход проверки DEX‑целостности и подписи через Frida‑хуки на соответствующие функции. Проверка, что приложение не «падает» после модификации.
  6. Имитация пользовательского поведения. После полного обхода проверок — автоматизация действий (логин, платежи) через Appium или UI Automator для масштабирования исследований.

Заключение: эмуляция — это не взлом, а танец на грани​

Эмуляция мобильных банковских приложений — это не технологический трюк, а постоянная гонка вооружений между защитой и исследователем. Обфускация, анти‑tamper, детекция эмулятора, проверки целостности — всё это становится прозрачным, если знать, куда смотреть и какой инструмент применить.

Сегодняшние банковские приложения проверяют не только root, но и сам факт модификации системы, наличие фреймворков динамической инструментации, целостность DEX и подписи. Обход каждого механизма требует понимания, как он устроен, и умения применить Frida, Objection или Magisk/LSPosed в нужный момент.

Три главных вывода:
  1. Статического анализа недостаточно. Обфускация и native‑проверки скрывают логику до момента выполнения. Без Frida или аналогичных инструментов невозможно понять реальное поведение приложения.
  2. Современный обход — это многоуровневая эмуляция. Вам нужно быть не просто rooted‑устройством, а убедительной копией чистого, немодифицированного телефона. Каждый слой защиты требует своего слоя маскировки.
  3. Native‑код — последний бастион. Самые хитрые проверки всегда выносятся в C/C++ .so‑библиотеки. Их обход требует либо глубокого реверс‑инжиниринга, либо специфических хуков на системные вызовы и доступа к памяти.

Быстрая памятка на одну строку:
«APKTool распакует, JADX покажет, Frida перехватит, Objection обойдёт, Magisk спрячет, LSPosed подменит. Каждый слой защиты требует своего инструмента, но без понимания логики приложения — это просто набор команд. Эмуляция — это не взлом, а искусство быть незаметным.»
 
Top