CIOlogia Безопасность бизнеса · не на словах, а с доказательствами
← Все разборы Мобильная безопасность

Как «обновление банка» из мессенджера увело 380 000 ₽ со счёта компании: разбор Android-трояна с подменой окон

Менеджер по снабжению установил файл по ссылке из мессенджера — и через неделю компания лишилась 380 тысяч рублей. Разбираем механику атаки на уровне Android-разрешений, инструментов анализа и того, почему такие трояны опасны для сотен банков одновременно.

Разбор CIOlogia

История стандартная для малого и среднего бизнеса: оптовая компания, 15 сотрудников, у менеджера по снабжению — рабочий телефон с привязанным к нему расчётным счётом. Ночью с этого счёта уходят два перевода на 380 000 рублей суммарно, банк присылает подтверждение, менеджер спит. Формально операция подтверждена с устройства владельца счёта — значит, для банка это не мошенничество, а «клиент сам перевёл». Разбираться пришлось не с банком, а с телефоном.

Куда делись деньги

За неделю до списания менеджеру в мессенджер пришла ссылка: «обновите приложение банка, иначе доступ будет заблокирован». Ссылка вела не в Google Play, а на сторонний сайт с файлом APK. Установка прошла в обход официального магазина — при первом запуске приложение запросило права на службу специальных возможностей (Accessibility Service) и на отображение поверх других окон. Пользователь эти права выдал, посчитав их частью «настройки безопасности банка».

С этого момента устройство фактически перестало принадлежать владельцу. Троян умеет три вещи одновременно: читать содержимое экрана и уведомлений через Accessibility API, рисовать поддельный интерфейс поверх настоящего приложения (overlay-атака) и перехватывать входящие SMS раньше, чем их увидит пользователь. Когда менеджер открывал настоящее банковское приложение, троян детектировал имя пакета на переднем плане и за доли секунды подменял экран собственной копией — визуально неотличимой. Введённые логин, пароль и код из СМС уходили не в банк, а на сервер злоумышленников, а настоящий банк в это время получал легитимный, только что перехваченный код подтверждения.

Почему это не «вирус для одного банка»

Современные семейства таких троянов (в духе публично описанных TeaBot/Anatsa, Cerberus/Octo, Hook, Vultur) не пишутся под конкретный банк. Overlay и парсинг экрана строятся так, что вредонос сравнивает foreground-пакет (com.android.systemui → активный app) со списком из сотен банковских и криптокошельковых приложений и подгружает нужный шаблон фишингового окна с сервера управления (C2) уже после заражения. Это ровно тот случай, который описан в новости о 349 атакуемых приложениях: список целей не зашит статично в APK, а обновляется удалённо, поэтому антивирусные сигнатуры отстают.

Как это эксплуатируется — по шагам

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

1. Доставка

Фишинговое сообщение в мессенджере или SMS со ссылкой на сторонний хостинг APK. Проверка такого домена стандартным инструментарием разведки:

curl -I https://fake-bank-update.ru/app.apk

HTTP/1.1 200 OK
Server: nginx
Content-Type: application/vnd.android.package-archive
Content-Disposition: attachment; filename="Bank_Update.apk"

Домен зарегистрирован несколько дней назад, сертификат Let's Encrypt, никакого редиректа на официальный сайт банка — классические признаки одноразовой фишинговой инфраструктуры.

2. Установка в обход Google Play

Ключевое условие атаки — разрешённая установка «из неизвестных источников». Проверить состояние настройки на устройстве:

adb shell settings get global install_non_market_apps
1

Единица означает, что установка сторонних APK разрешена — именно так троян и попал на телефон менеджера.

3. Статический анализ вредоносного APK

При разборе инцидента я разворачиваю образец в изолированной песочнице (эмулятор без сети или отдельный физический тестовый телефон) и смотрю манифест и код:

apktool d Bank_Update.apk -o bank_update_decoded
grep -E "uses-permission|service" bank_update_decoded/AndroidManifest.xml

Типичный набор разрешений в таких образцах:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<service android:name=".AccessService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService"/>
    </intent-filter>
</service>

Комбинация SYSTEM_ALERT_WINDOW + BIND_ACCESSIBILITY_SERVICE + доступ к SMS — практически всегда сигнатура overlay-трояна, независимо от названия семейства. Для более глубокого разбора логики подмены окон удобен jadx:

jadx-gui Bank_Update.apk

В декомпилированном коде обычно находится список пакетов-целей (ru.sberbankmobile, ru.vtb24.mobilebanking, com.idamob.tinkoff.android и т.д.) и метод, который слушает onAccessibilityEvent для отслеживания смены переднего окна.

4. Динамический анализ и подтверждение поведения

Для проверки, что именно происходит в момент открытия «банка», используется Frida — трассировка runtime-вызовов без исходников:

frida -U -f com.fake.bankupdate -l trace_overlay.js --no-pause

[*] onAccessibilityEvent: package=ru.sberbankmobile.online
[*] launching overlay activity: FakeLoginActivity
[*] SMS intercepted: code=482913, forwarded to C2

Более быстрый вариант для массовой проверки корпоративного парка APK — автоматизированный статический+динамический анализ через MobSF в докере:

docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf
# затем загрузка APK через веб-интерфейс localhost:8000

MobSF сразу подсвечивает опасные комбинации разрешений и обфусцированный код, характерный для банковских троянов.

5. Логи на стороне устройства

Если заражение уже произошло и нужно подтвердить факт для отчёта клиенту или страховой, полезно поднять logcat и поискать привязку службы специальных возможностей:

adb logcat | grep -i accessibility

AccessibilityManagerService: Accessibility Service com.fake.bankupdate/.AccessService connected

Появление незнакомого пакета в списке подключённых Accessibility-сервисов — прямое доказательство компрометации.

Что и почему сработало бы дальше

380 000 рублей — это только то, что успели увидеть. Получив Accessibility-доступ, троян обычно не останавливается на одном банке:

  • Перехватывает коды из push- и SMS-уведомлений любых других приложений — почты, мессенджеров, крипто-кошельков, второго банка, если он тоже установлен на этом телефоне
  • Через Accessibility API имитирует нажатия — то есть может сам, без участия жертвы, кликать по кнопкам подтверждения перевода, если пользователь не успел заблокировать телефон
  • В более развитых семействах есть модуль удалённого управления экраном (по типу VNC поверх MediaProjection), позволяющий оператору дистанционно управлять устройством в реальном времени
  • Список контактов и переписка в мессенджерах используются для рассылки той же фишинговой ссылки — так атака масштабируется на других сотрудников и партнёров компании

Именно поэтому расследование одного инцидента на 380 000 ₽ всегда должно сопровождаться полной проверкой остальных корпоративных телефонов, а не только пострадавшего устройства.

Во что это обошлось компании

Прямые потери — 380 000 рублей, банк деньги не вернул: с юридической точки зрения операция подтверждена корректным кодом с устройства держателя счёта, и доказать факт компрометации телефона постфактум сложно. Косвенные потери оказались не меньше: неделя работы собственника ушла на переписку с банком и заявление в полицию вместо переговоров с поставщиками, а к менеджеру, который формально «сам всё подтвердил», временно перестали допускать переводы — хотя причиной была дыра в настройках телефона, а не человеческая ошибка в моменте платежа.

Как закрыли

Работы заняло два дня на весь парк рабочих телефонов, без внедрения дорогих систем.

  1. Запрет установки из сторонних источников на уровне управления устройствами (Android Enterprise / MDM), а не только через системную настройку, которую пользователь может включить обратно:

    adb shell settings put global install_non_market_apps 0
    adb shell dpm set-device-owner com.company.mdm/.AdminReceiver
    

    Через управляемый Google Play (Android Enterprise) применяется корпоративная политика с белым списком приложений:

    {
      "applications": [
        { "packageName": "ru.sberbankmobile.online", "installType": "REQUIRED" },
        { "packageName": "com.company.internalapp", "installType": "REQUIRED" }
      ],
      "playStoreMode": "WHITELIST",
      "unknownSourcesAllowed": false,
      "adjustVolumeDisabled": true
    }
    

    При такой политике установка APK вне разрешённого списка физически недоступна пользователю без прав администратора MDM.

  2. Переход с SMS-кодов на приложение-аутентификатор (TOTP: Google Authenticator, Яндекс Ключ или банковский аутентификатор с привязкой к устройству). Такие коды не проходят через SMS-канал и не читаются напрямую через READ_SMS, что заметно повышает сложность перехвата — overl