Security Lab

«MAX» под микроскопом — как дружелюбный мессенджер превращается в инструмент слежки

«MAX» под микроскопом — как дружелюбный мессенджер превращается в инструмент слежки

Один из участников сообщества GitHub выложил в открытый доступ репозиторий, в котором провёл детальный разбор работы приложения MAX и описал, какие именно механизмы используются для сбора пользовательских данных. Исследование оказалось достаточно обстоятельным, чтобы вызвать интерес не только у специалистов по безопасности, но и у более широкой аудитории. Я не занимался самостоятельным техническим анализом приложения, а подготовил данный пост уже на основе этого исследования. Таким образом, мой материал рассматривается не как исходное разоблачение, а как пересказ и объяснение найденных фактов для тех, кто хотел бы понять суть происходящего без необходимости самостоятельно изучать исходный код.

Приложение «Макс» внешне выглядит как современный мессенджер, готовый конкурировать с признанными лидерами за счёт «быстрых и лёгких» коммуникаций, качественных звонков, анимированных стикеров и возможности пересылать файлы до 4 ГБ. Оно доступно практически везде — на Android через Google Play, RuStore и AppGallery, на iOS через App Store и в десктопных версиях, а в файле AndroidManifest.xml ему соответствует пакет ru.oneme.app. Однако под гладкой оболочкой скрывается высокоинтрузивная система «чтения», искусно маскируемая глубокой обфускацией кода и опирающаяся на богатый набор разрешений и фоновых сервисов.

Почти весь критический функционал вынесен в модуль com.my.tracker, при этом его часть помещена в подпакет com.my.tracker.obfuscated. Там имена классов, методов и переменных сведены к абстрактным e0, c1, y2, b3, f1 и одно­буквенным a(), b(), c(), что почти исключает статический анализ без предварительной деобфускации. Такой приём обычно используют либо чтобы сохранить коммерческие тайны, либо чтобы скрыть сомнительную логику. В случае «Макса» признаки второго сценария выражены особенно ярко: трекер собирает детальнейшую телеметрию, отслеживает каждое действие пользователя и способен передавать на сервер огромные массивы персональных и системных данных.

Файл MyTracker.java играет роль фасада: публичные статические методы initTracker, trackEvent, trackAdEvent, trackPurchaseEvent, startAnytimeTimeSpent и десятки других делегируют вызовы в обфусцированный класс c1, а тот уже взаимодействует с инфраструктурой трекера. Инициализация требует лишь ID и контекста приложения, после чего c1 начинает буферизовать события и паковать их во внутренний формат с помощью класса f1, а затем отправляет через сеть при первом же удобном случае (метод e0.c() проверяет подключение и инициирует выгрузку).

Категории собираемых данных впечатляют масштабом. 

  • События взаимодействия: клики по рекламе, покупки в Google Play и AppGallery с передачей ID товара, цены, валюты и arbitrary parameters, приглашения, регистрации, входы, запуски, переходы по уровням, активность в мини-приложениях, произвольные трекинговые события по выбору разработчиков и точное время, проведённое в приложении или в конкретном сценарии. 
  • Персональная информация: возраст, пол, пользовательские идентификаторы (включая customUserId и их массивы), адреса электронной почты, номера телефонов, ICQ ID, OK ID, VK ID, VK Connect ID, а также язык интерфейса и целая россыпь специальных идентификаторов MRGS. Любой из этих параметров можно как прочитать, так и записать; кроме того, через setCustomParam разработчик вправе передать буквально любые «ключ-значение», расширяя объём собираемой информации до бесконечности. 
  • Атрибуция: трекер фиксирует диплинки, откуда пользователь попал в приложение, вычисляет источник установки и хранит сведения о предустановках, в том числе от сторонних партнёров.

Чтобы эта махина работала без сбоев, ей требуются соответствующие права. Manifest выстроен как каталог желаний особо ненасытного приложения. Разрешения INTERNET, ACCESS_NETWORK_STATE и ACCESS_WIFI_STATE — лишь базис. Далее идут:

  • ACCESS_FINE_LOCATION и ACCESS_COARSE_LOCATION для точной и приблизительной геолокации, 

  • CAMERA и RECORD_AUDIO для доступа к камере и микрофону,

  • BLUETOOTH* для полного управления беспроводными соединениями, 

  • READ_CONTACTS и WRITE_CONTACTS для полного обращения с контактами, 

  • READ_PHONE_NUMBERS для чтения номера устройства, 

  • целый набор *_STORAGE и READ_MEDIA_* для доступа к файлам и медиаконтенту, 

  • GET_ACCOUNTS / MANAGE_ACCOUNTS / USE_CREDENTIALS для манипуляций с учётными записями, 

  • POST_NOTIFICATIONS для пушей, 

  • REQUEST_INSTALL_PACKAGES для установки сторонних APK, 

  • SYSTEM_ALERT_WINDOW для отображения поверх всех окон, 

  • WAKE_LOCK и DISABLE_KEYGUARD для управления энергией и блокировкой, 

  • FOREGROUND_SERVICE и, что особенно тревожно, foregroundServiceType="microphone|camera|location|mediaProjection|mediaPlayback|dataSync". Последний флаг означает, что приложение может в фоне записывать звук, видео, перемещения и даже делать захват экрана, выдавая пользователю лишь формальное уведомление о «фоновой работе».

Архитектура компонентов выстроена так, чтобы закрепиться намертво. BroadcastReceiver BootCompletedReceiver реагирует на полную загрузку системы и автоматически пробуждает приложение. Для постоянных задач используются Foreground Service SystemForegroundService и CallServiceImpl. Первый получает доступ к микрофону, камере, GPS и синхронизации данных, второй дополнительно умеет захватывать экран. Служба ContactsSyncService регистрируется как адаптер синхронизации контактов, что позволяет регулярно выкачивать адресную книгу. LinkInterceptorActivity перехватывает HTTP/HTTPS-ссылки, относящиеся к собственным доменам, что не только упрощает диплинки, но и даёт возможность анализировать или модифицировать трафик внутри экосистемы «Макса».

Отдельного внимания заслуживает возможность захвата экрана через mediaProjection. Раз сервис объявлен в манифесте, значит, код внутри CallServiceImpl или соседних классов способен инициировать захват изображения дисплея при любом удобном случае. Комбинация с микрофоном создаёт предпосылки для тихой записи звонков и видеочатов, а флаг mediaPlayback намекает на возможность выводить собственный аудиопоток поверх других приложений.

Попытка ручного «расковыривания» обфусцированных классов e0 и f1 показывает только верхушку айсберга. e0 формирует частичные пакеты, логирует промежуточные статусы (createAndStorePartialPacket: start / writeResult=…), следит за буфером и вызывает сетевую отправку при наличии соединения. f1 управляет структурой пакета: добавляет новые элементы, сбрасывает буфер при успешной доставке, пересобирает пакеты при ошибках. Логика доставки абстрагирована, но внутри фигурирует MyTrackerConfig.OkHttpClientProvider — значит, транспорт построен на OkHttp, поддерживающем прокси, кастомные интерцепторы, собственные TrustManager-ы и гибкие таймауты. Если разработчики захотят обойти проверку TLS-сертификатов или подменить трафик, у них есть все необходимые крючки.

При этом прямого патчинга системы или эксплуатации root-прав манифест не демонстрирует. Нет ни WRITE_SECURE_SETTINGS, ни MOUNT_UNMOUNT_FILESYSTEMS, ни BIND_DEVICE_ADMIN, ни упоминаний о su-бинарях. Но необходимость в эксплойтах исчезает, когда пользователь добровольно выдаёт столь щедрый набор разрешений: приложение получает тотальный доступ к датчикам и данным через штатные API. А службы гарантируют непрерывность слежки: устройство может спать, экран — тухнуть, а «Макс» будет тихо стримить координаты, аудио и видео на свои серверы.

Поверх системной слежки приложение внимательно записывает сам контент мессенджера. В protobuf-структурах ru.ok.tamtam.nano обнаружены поля lastInput, lastInputEditMessageId, lastInputMedia и lastInputReplyMessageId — это история последних действий в поле ввода, включая черновики и ссылки на медиа. Таким образом, даже неотправленные сообщения, удалённые до публикации, способны навсегда остаться в бэкэнде.

Нельзя оставить без внимания и возможность установки сторонних APK. REQUEST_INSTALL_PACKAGES сам по себе не страшен, пока пользователь не подтвердит установку, но в связке с SYSTEM_ALERT_WINDOW и навязчивыми уведомлениями можно организовать «социальную» атаку: показать окно поверх текущего приложения, подсунуть «обязательное обновление» и убедить пользователя нажать «Установить». Как только жертва согласится, «Макс» расширит свои полномочия ещё одним модулем, потенциально обходящим ограничения магазина.

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

На практике любой обладатель «Макса» носит в кармане сенсор, который фиксирует его перемещения, общение, покупки и даже мимолётные мысли, не предназначенные для отправки. Технически это реализовано легальными средствами Android, без эксплойтов и root-хака, но масштаб остаётся пугающим: достаточно один раз запустить мессенджер, и он уже прописывается в автозапуск, постоянно держит руку на микрофоне, камере и GPS и умеет самостоятельно обновляться сторонними модулями.

Max код Макс мессенджер разбор
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.

 Время и пространство — это обманка.

То, что ты видишь как «реальность», на самом деле сеть причин и следствий. Каждая мысль, каждый шаг — новый узел в этой паутине. Но большинство людей даже не подозревают об этом.

Комнатный Блогер

Объясняю новую цифровую реальность