Средство связи MAX: моё мнение

Часть 2.1: про анализ приложения

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

После второй части я честно хотел перейти к третьей, в которой бы описал своё личное отношение к конкретной реализации «национального средства коммуникации» от VK под названием MAX. Однако коллега подкинул очередной «разбор»/«анализ» Макса и не где-нибудь, а на Хабре.

Это один из типичных анализов Макса, которые сводятся к чтению Манифеста, даже без попытки заглянуть в код (но да, он обфусцирован). Возьму его как просто один из множества, всё равно они все похожи: взяли Манифест и закинули ИИшке, которая пук-среньк и написала чушь.

Хотя именно в этом “разборе”, мне кажется, ИИ особо не участвовал. Я читал уже удалённый, самый первый, который стал популярным. Вот там вообще ИИ бред был очевиден.

Замечание о внешних файлах. Скриншоты я не храню у себя, а буду ссылаться на них в оригинальных статьях. Так что если со временем статья будет недоступна, то и скриншоты будут недоступны.

MAX без оболочки: Что мы нашли в его APK

Доступ к контактам

После того, как я ввел номер телефона и подтвердил его, «Макс» попросил доступ к моим контактам (Рисунок 1). Достаточно стандартное поведение для мессенджера, позволяет находить контакты из списка, зарегистрированных в «Максе»

Рис. 1:

Рис.1 Запрос доступа

После этого, «Макс» снова запросил доступ к контактам (рисунок 2).

Рис. 2:

Рис.2 Запрос доступа

Строго говоря, это не является ошибкой разбора. Это кривой UX — реально одна из важных проблем MAX. На первом скриншоте нет никакого запроса доступа, хотя и похоже на него. По рекомендациям Google, перед запросом некоторых (не всех) разрешений, нужно сначала объяснить, зачем они нужны. И то, это правило довольно жидкое. Если пользователю так понятно, зачем разрешение запрашивается, то предварительного объяснения не нужно. Например, пользователь нажимает «Поделиться местоположением». Приложение сразу же может запросить разрешение на местоположение, если оно ещё не предоставлено. Потому что пользователь точно понимает, к чему этот запрос. А вот другая ситуация. Приложение может выполнять автоматические фоновые работы и, важно, может это делать в любых Wi-Fi сетях или конкретных. И тут проблема. Если пользователь желает выполнять фоновые работы только в своей домашней Wi-Fi сети, нужно запросить разрешение на геолокацию. Это происходит потому что получать расширенные данные о Wi-Fi точке можно только при наличии такого разрешения. Но пользователь ведь этого не знает. В этом случае сначала можно написать, что так и так, если выберешь такой вариант, придётся предоставить такое разрешение.

Доступ к контактам — это действительно не самая нужная вещь для средства общения, т.к. он вполне может использовать и свою записную книгу, не зависимую от системы. Так что это нормально — сначала объяснить, что далее будет такой-то запрос и вот почему. Но объяснение нарисовано отвратительно, как и вообще весь UI Макса. Он совершенно не похож на другие приложения и, самое главное, на ОС, в которой работает. Это объяснение действительно очень похоже на запрос разрешения, только в iOS. Но это не оно, это такое кривое объяснение. А вот второй скриншот — это правда системный запрос.

были запрошены доступ к камере, демонстрации и записи экрана (демонстрация экрана в звонке есть, а вот функционала записи я не увидел)

Рис.4 Запрос доступа к камере, демонстрации и записи экрана.

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

AndroidManifest.xml — один из самых важных и интересных для исследователя файлов. Он содержит много информации, по которой можно составить представление о приложении, и даже сформировать поверхность атаки. В архиве он представлен в закодированном виде.

Не буду считать это ошибкой, скорее, просто привычное для рядовых читателей слово. Но это не закодированный, а просто бинарный формат файла. Это Google так делает, это не какая-то защита от авторов.

REQUEST_INSTALL_PACKAGES – может устанавливать другие приложения

Если быть точным, то может запросить разрешение на установку приложений, а его можно и не предоставить. Потому что в Android ни одно приложение не может ставить другие. Это доступно только встроенному PackageManager. Остальные могут лишь просить его что-то установить. Оно потому и называется REQUEST_* К сожалению, очень много приложений объявляют это разрешение без реальной необходимости. Оно есть у Chrome, Firefox, WhatsApp и многих других. Кто-то объявляет его «для удобства», например браузеры. Кто-то — потому что правильно боится, что его могут вышибыть из Google Play, а обновиться как-то нужно.

Конкретно MAX, возможно, но маловероятно (проверить сложно, т. к. установка в Android вызывается не для packageManager), объявил это разрешение как раз для самообновления. Но, даже если это так (опять же, сомневаюсь, т.к. в коде вижу обновления через GPlay), он всё равно позволяет ставить любые другие приложения, если пользователь попытается это сделать.

Я считаю, что это очень плохое свойство для национального средства общения. Если бы я участвовал в разработке Макса, то разрешение реально было бы в Манифесте (на случай самообновления), но если обнаруживается, что в системе установлен поддерживаемый магазин, то вызывал бы API для проверки существования себя в Магазине. И, если обнаруживал бы, то запрос разрешения бы блокировался. То есть тап в чате на apk файл приводил бы только к сохранению, но не к запуску. В случае, если в Магазине он себя не находил бы, то должен делать следующее:

Резюмируя: стандартное, но плохое, разрешение, которое многие отечественные производители используют для самообновления. Но к конкретно Максу выдвигаются (мною) повышенные требования безопасности и он не должен даже пытаться устанавливать apk, если обнаруживает, что его не выперли из магазинов.

К сожалению, автор «исследования» не озаботился нормальным объяснением и предложением своего подхода.

SYSTEM_ALERT_WINDOW – может показывать окна поверх других приложений

Уже не имеет смысла. Это устаревшее разрешение и сейчас, чтобы его получить, нужно прям постараться. На современных версиях Android без помощи Google вообще мало кто сможет понять, как это разрешение предоставить. Я уверен, что это хвост от родителя Макса, кем бы он ни был (Там-Там, Сферум, что там ещё). Современный же способ показывать себя поверх других окон — это использовать полноэкранные уведомления. Они то как раз и защищены разрешением android.permission.USE_FULL_SCREEN_INTENT, о котором исследователь написал ниже. Это критически важное разрешение для любой звонилки (если у неё нет «роли звонилки» — очень специфичное API, который MAX не использует). Без него нельзя показать экран принятия или сброса звонка.

Резюмируя: устаревший и бесполезный. Его нельзя выдать. Разработчики удалят его, когда руки дойдут. Сейчас он просто объявлен, но ничего не делает.

RECEIVE_BOOT_COMPLETED – автозапуск при старте системы

В целом да, но давайте более полно опишем суть этого ресивера. Если он объявлен в Манифесте, то Android, после загрузки и, важно, разблокирования устройства, пошлёт уведомление об этом событии приложению. Приложение не просто запустится. Оно, собственно, не может «запуститься» в терминах Windows, к примеру. Но зато приложение сможет выполнить критические для него действия. К примеру, обновить токен для пушей (иначе пуши отвалятся), пересоздать задачи для фоновых работ. И, важно, делать это приложение может не бесконечно долго. Android уже давно сильно ограничивает работу фоновых приложений. Так что Макс, как и абсолютно все другие, просто выполнят всякие прям критические для них задачи и на этом успокоятся. Запустится, а потом закешируется системой, лишь один и множества компонентов приложения.

Что важно — этот ресивер сам разработчик может иногда даже не объявлять, а оно всё равно будет. Вот пример с моим приложением: https://gitea.myachin.xyz/umnik/SaveTo/src/branch/master/app/src/main/AndroidManifest.xml Вы можете видеть, что получатель не объявлен мною в Манифесте, но он есть в приложении всё равно. Потому что я использую библиотеку для создания задач (чищу кеш периодически) от Google, а вот она уже добавляет ресивер при сборке, т.к. он ей нужен ей самой.

Резюмируя: стандарт. Есть примерно у всех.

DISABLE_KEYGUARD – отключение блокировки экрана

Сразу несколько раз неправильно. Вот правильно: – отключение работаЛО, только если экран блокирования не является безопасным. Другими словами, если пользователь не включил ни пароль, ни паттерн, ничего, то приложение могло обойти экран. Например, тап на уведомление от приложение позволило бы сразу открыть его – отключение работаЛО до Androiod 4.0.3. С тех пор работать перестало

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

Резюмируя: не работает и уже исключено из Манифеста

USE_FULL_SCREEN_INTENT – полноэкранные уведомления

Да. Потому что SYSTEM_ALERT_WINDOW устарел и больше не работает.

Резюмируя: правильный современный способ показать что-то на весь экран. Например экран входящего звонка

READ_CONTACTS, WRITE_CONTACTS – полный доступ к контактам

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

Резюмируя: нормальное поведение для обычного, не секретного, средства общения

ACCESS_FINE_LOCATION – точная геолокация. Постоянное отслеживание точного местоположения пользователя в реальном времени.

Да. Нет.

Да — это разрешение для получения более-менее точной геолокации. А ещё оно же нужно для того, чтобы узнать имя Wi-Fi сети, о чём я писал ранее. Этим разрешением много что защищено, к сожалению. Раньше даже обнаружение блютуз устройств им защищалось.

В Максе действительно есть возможность поделиться своим местоположением. Разрешение не запрашивается, пока не попытаешься поделиться впервые. Можно выдать на один раз. Кстати, если не выдать разрешение, то можно увидеть сообщение, которое описывает возможные будущие возможности. Например, поиск собеседников поблизости.

Нет — для отслеживания в реальном времени нужно ещё запросить разрешение на фоновую геолокацию. Иначе как только свернёшь приложение, доступ фиче пропадёт. Разрешение называется ACCESS_BACKGROUND_LOCATION и в последней версии оно не объявлено в Манифесте.

Резюмируя: разрешение нужно для вполне конкретной возможности и используется по назначению. Фоновое получение геолокации невозможно.

CAMERA – доступ к камере

RECORD_AUDIO – запись аудио

Разрешите я объединю их вместе. Эти разрешения нужны для звонков, а второе, дополнительно, для записи голосовых сообщений. Оба их можно выдавать одноразово. Оба они запрашиваются только при реальной необходимости. Для современного средства коммуникации это обязательные (в Манифесте) разрешения.

Резюмируя: очевидно нужные разрешения, запрашиваемые по делу.

READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE – доступ к файловой системе

Да, но с оговорками. Оба эти разрешения уже устарели. Посмотрите на скриншот из статьи:

Рис. 15

Если что, вот дополнительно скопировал из Манифеста только что:

     <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32"/>
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28"/>

Обратите внимание, что разрешения ограничены до Android 9 и Android 12. То есть если у вас Android 13 и новее, этих разрешений не будет в принципе. Дополнительно здесь можно снова увидеть, что в приложении остались хвосты родителя. Потому что android:maxSdkVersion="28" говорит, что на версиях 29 и новее (это 9-ка) разрешение не используется, а android:minSdkVersion="29" в этом же Манифесте говорит, что apk в принципе нельзя поставить на Android ниже 10.

Резюмируя: устаревший способ, оставленный для обратной совместимости на уже устаревших версиях Android.

READ_MEDIA_IMAGES, READ_MEDIA_VIDEO – доступ к медиафайлам

Да. Это современный способ, который появился в Android 13. Его прелесть в том, что он не даёт приложению просто так ходить по вашей файловой системе. Система отдаёт вам на управление, какие файлы приложение может получить, какие не может.

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

READ_PHONE_NUMBERS – доступ к телефонным номерам

Резюмируя: разрешение уже удалено в последней версии.

GET_ACCOUNTS, AUTHENTICATE_ACCOUNTS, MANAGE_ACCOUNTS, USE_CREDENTIALS – полный доступ к аккаунтам. Может получить список всех аккаунтов (Google, соцсети, почта) на устройстве и манипулировать ими.

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

GET_ACCOUNTS — это действительно разрешение. Оно нужно для получения списка учётных записей. Вполне себе обыденное действие для любого приложения, которое эти учётные записи в системе создаёт. Обращали внимание, что одно приложение часто позволяет авторизоваться сквозь другое, а иной раз без необходимости вообще что-то делать, кроме как нажать “Войти”? Вот этот механизм работает через учётные записи. К примеру, приложения Яндекса создадут вам учётную запись и все новые приложения от Яндекса в вашей системе попытаются найти, может уже есть авторизованная учётка. Если да — переиспользуют её.

AUTHENTICATE_ACCOUNTS, MANAGE_ACCOUNTS и USE_CREDENTIALS – это вообще адок. Google УДАЛИЛ эти разрешения из системы. Не объявил устаревшими, а вообще удалил, будто их никогда и не было. Вы можете до сих пор встретить их в уже устаревшей документации, но вы не найдёте их среди известных даже с пометкой Deprecated.

Резюмируя: разрешения уже удалены из кода в последней версии.

USE_FINGERPRINT – доступ к биометрии

Как-то странно сформулировано. Это не доступ к биометрии, а возможность повесить биометрию как способ разблокирования приложения. Думаю, блокировку приложения через биометрию вы все видели миллион раз.

Это, кстати, устаревшее, хотя и работающее разрешение. Оно устарело в Android 9 (напомню, Макс требует минимум Android 10) и на смену ему пришло USE_BIOMETRIC. И в Максе оно тоже объявлено в последней версии приложения. Значит устаревшее скоро удалят, просто руки ещё не дошли.

Резюмируя: нормальное разрешение для средств общения. Уже заменяется на актуальное USE_BIOMETRIC.

INTERNET – полный доступ в интернет

Да. Только не понимаю, к чему тут слово «полный». Это разрешение одинаково хоть для полного, хоть для частичного. Если используешь сетевые запросы хоть в каком-то виде, будь добр объявить это разрешение.

Резюмируя: нормальное разрешение для средств общения.

ACCESS_WIFI_STATE, ACCESS_NETWORK_STATE – мониторинг сети

Ну, вроде и не соврал, но как-то сформулировано гаденько, учитывая тон статьи. Эти разрешения нужны чтобы просто понять, можно ли в этой сети работать или нет. При чём сам Google говорит, что это не опасные разрешения и Android выдаёт их автоматически. Они не позволяют понять, где ты находишься, к примеру. Но позволяют узнать, жива ли сеть, платная ли она. Эти разрешения даже не обязательно объявлять вручную, см. пример выше с получателем уведомления о загрузке. Эти разрешения автоматически добавляют библиотеки Google для всяких фоновых работ. Потому что может быть тяжёлая задача, типа отправки файла в фоне на полгига. Хорошо бы её выполнять в нетарифицируемой (бесплатной) Wi-Fi сети. Приложение, когда создаёт задачу, выставляет такие флаги и библиотека берёт на себя понимание, подходит ли конкретно та сеть, к которой подключены прямо сейчас, для задачи или нет. При чём второе разрешение нужно для тех же мобильных сетей. Скажем, не грузить файлы в роуминге.

Резюмируя: нормальные разрешения для средств общения, где может быть большой трафик.

Bluetooth разрешения – полный контроль Bluetooth

Сначала дам скриншот из статьи:

Рис. 21

Во-первых, разрешения уже режут, т. к. часть из них устарела или не имеет смысла:

    <uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

Во-вторых это не полный контроль, а просто подключение беспроводной гарнитуры для общения голосом. В-третьих уже устаревающий, но ещё живое разрешение android.permission.BLUETOOTH ограничено сверху и не существует на Android 12 и новее. Там уже используется современное android.permission.BLUETOOTH_CONNECT.

Резюмируя: нормальные разрешения для средств общения.

CHANGE_WIFI_STATE – изменение состояния Wi-Fi. Могут мешать работе сети, перехватывать трафик.

  1. Уже удалено, его нет сейчас в Манифесте
  2. Даже если бы не было удалено, Андроид уже давно не позволяет управлять Wi-Fi сетями. Приложение может управлять Wi-Fi сетью, только если оно само её и создало (не считаем всяких админских прав и системные приложения). Остальные идут лесом

Резюмируя: уже удалённый хвост. Использовался когда-то для просто понимания состояния сети.

[Подозрительный] Сервис для звонков с доступом к камере и микрофону

        <service
            android:name="one.me.calls.impl.service.CallServiceImpl"
            android:exported="false"
            android:foregroundServiceType="microphone|camera|mediaProjection|mediaPlayback"/>

Думаю, иметь сервис для звонков для звонилки — это не подозрительно. Но разберём, что тут написано, потому что это просто полезно.

Для начала нужно понять, что такое foreground service (сервис переднего плана). Сервис — это такой компонент приложения, который не имеет UI и используется для длительных работ. К примеру, нужно вам скачать файл — имеет смысл переложить эту задачу на сервис. Сервисы могут быть фоновые (background) и переднего плана. О существовании фоновых пользователь не знает и не видит их. А вот сервисы переднего плана обязаны создать видимое пользователю уведомление. Если его не создать, Андроид убьёт сразу убьёт приложение. Типичный пример — музыкальный плеер. Они не просто так уведомления вешают, хоть это и удобно. Если не повесят — они не смогут работать в фоне.

Современный Андроид работает так, что если пользователь чего-то не видит и это что-то не системное или не имеет особенных, очень сложно получаемых прав, то это что-то будет убито.

Резюмируя: абсолютно корректное объявление необходимого сервиса переднего плана

[Подозрительный] Сервис медиа-проекции (может записывать экран)

        <service
            android:name="ru.ok.tamtam.android.calls.MediaProjectionService"
            android:exported="false"
            android:foregroundServiceType="mediaProjection"/>

Хотя фича трансляции экрана есть и даже используется в CallServiceImpl, я не нашёл в коде приложения вызова этого сервиса. Больше всего это похоже на хвост от ТамТам, который будет удалён в будущих версиях. Сейчас это просто мёртвый код, никем не вызываемый. Т. к. android:exported="false", то можно быть уверенным, что и сторонние приложения этот код не смогут вызвать.

Резюмируя: мёртвый код, который ещё не удалили. Актуальный код находится в one.me.calls.impl.service.CallServiceImpl.

android:exported="true" (Критическая уязвимость). Эта активность может быть запущена извне — другим приложением на устройстве или даже из браузера по специальной ссылке.

Нет, это не уязвимость, а нормальное поведение для глубоких ссылок/дип линков (deeplink). Они для этого и созданы.

android:excludeFromRecents="true" (Тактика скрытности). После того как пользователь завершит работу с этой активностью, она не появится в списке последних приложений (который вызывается кнопкой “Недавние”).

Это рекомендуемое поведение для глубоких ссылок.

Давайте разберёмся, что такое глубокие ссылки. Странное название, правда? Вот простая ситуация: вам нужно объяснить человеку, как найти в RuStore какой-нибудь MAX. Нужно объяснять, как запустить РуСтор, что написать в поиске, какое из найденных приложений выбрать. А можно просто прислать ссылку market://details?id=ru.oneme.app и Андроид спросит, каким Магазином её открыть. Выбери хоть Google Play, хоть RuStore — откроется сразу правильный экран. Глубокие ссылки позволяют открыть сразу нужный экран приложения, в какой бы жопе этого приложения он не был. Можно даже сделать экраны, которые кроме как по глубоким ссылкам недоступны.

Теперь понятно, почему android:exported="true"? Иначе же внешние приложение не сможет экран открыть. И очевидно, что в списке Недавних экраны сотой глубины вложенности не нужны. Потому вполне разумно их исключить.

Вот как на самом деле выглядит код, кусочек которого предоставил автор:

        <activity
            android:theme="@style/OneMe.Theme.Transparent"
            android:label=""
            android:name="one.me.android.deeplink.LinkInterceptorActivity"
            android:exported="true"
            android:excludeFromRecents="true"
            android:launchMode="singleTop"
            android:configChanges="orientation"
            android:windowSoftInputMode="adjustResize|stateHidden">
            <intent-filter
                android:label="max"
                android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:pathPattern="/..*"/>
                <data android:scheme="http"/>
                <data android:scheme="@string/web_scheme"/>
                <data android:host="@string/app_host"/>
            </intent-filter>
            <intent-filter android:label="max">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="@string/app_scheme"/>
                <data android:host="@string/app_host"/>
            </intent-filter>
            <meta-data
                android:name="android.app.shortcuts"
                android:resource="@xml/shortcuts"/>
        </activity>

Не буду разбирать построчно, просто соберу в итог. Андроид, закрепи за мной ссылку http[s]://max.ru/*. Если кто-то попытается эту ссылку открыть, то я её обработаю вот этим экраном.

Разумеется, в Google не совсем дураки сидят и просто так закрепить за собой ссылку ты не можешь. Ты должен по указанному адресу положить специальный файл (max.ru/.well-known/assetlinks.json), который позволит удостоверить, что ты действительно имеешь право на перехват этих ссылок.

Например, если вы установите альтернативный YouTube клиент, вам вручную нужно будет назначать ссылки для перехвата. Они объявлены в Манифесте, но Андроид их не включит, вы должны сделать это руками.

В общем, в этом примере Андроид передаст Максу ссылки только на его собственный сайт.

Резюмируя: нормальное поведение для множества приложений.

[Опасный компонент] CallNotifierFixActivity с возможностью показа на экране блокировки

Кажется, уже по названию можно догадаться, что это такое. Вот код:

        <activity
            android:theme="@style/CallNotifierFixActivityTheme"
            android:name="one.me.android.calls.CallNotifierFixActivity"
            android:showOnLockScreen="true"
            android:turnScreenOn="true"/>

Использовалось когда-то для показа уведомления о звонке. Код немного изменят, т.к. showOnLockScreen объявлен устаревшим ещё в API 23. Напомню, что Макс не установится на API ниже 29.

Резюмируя: устаревший костыль.

com.google.android.gms.permission.AD_ID – доступ к рекламному ID

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

Резюмируя: иногда сигара — это просто сигара.

Отключено резервное копирование (allowBackup=“false”)

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

Тут прям всё не так. 1. Очень многие приложения, практически все, где есть учётные записи, запрещают резервное копирование 2. Разработчики несколько отстали от современности. Они выключили резервное копирование в облако (читай – в Google Drive). Но на переезд с одного устройства на другое эта настройка не влияет для всех современных устройств. То есть если вы возьмёте Pixel 8 и переедете по кабелю на Pixel 9, то приложение переедет. Вполне возможно переедет поломанным и нужно будет вручную чистить ему данные 3. Вредоносные приложения отключают, потому что зачем оно им. На их анализ это вообще никак не влияет

Резюмируя: нормальное поведение, когда в приложении есть учётные записи, хотя я сам такое и не люблю. Но правильная реализация требует прям заморочиться

Включен нативный код (extractNativeLibs="false")

Указывает системе не распаковывать нативные библиотеки (.so файлы) из APK. Это может использоваться для затруднения статического анализа кода антивирусами и исследователями, так как часть логики спрятана в скомпилированных бинарниках.

Палю крутой способ достать so файлы — архиватор, работающий с zip архивами.

На самом деле это рекомендуемое поведение. Оно говорит Андроиду, чтобы тот не извлекал нативные библиотеки, а просто читал из прямо из apk файла. Кроме того, этот флаг используется системой сборки gradle. Он говорит гредлу, чтобы тот не сжимал нативные либы, т.к. при сжатии прямого чтения из apk не получится. В итоге имеем бОльший размер apk, но бОльшую скорость чтения натива во время работы.

Резюмируя: обычное поведение.

DOWNLOAD_WITHOUT_NOTIFICATION – скрытые загрузки

На самом деле никогда не работало так, как вы того ожидаете. Даже в древние времена. А сегодня он вообще не работает. Как результат — в текущей версии Макса этого разрешения нет.

Резюмируя: не рабочий хвост старого приложения. Уже удалён.

FOREGROUND_SERVICE_DATA_SYNC – фоновая синхронизация данных

Позволяет запустить foreground-сервис для “синхронизации данных”. Это механизм для длительной фоновой работы под видом полезной деятельности, чтобы постоянно собирать данные

Вон чё. Вообще это разрешение, которые разработчики ОБЯЗАНЫ объявить, если используют сервис переднего плана с типом dataSync. Таких сервисов у них два: one.me.android.media.service.OneMeDownloadService, отвечающий за загрузку и androidx.work.impl.foreground.SystemForegroundService, который вообще не их, а пришедший к ним из гугловой библиотеки WorkManager, которую используют вообще все, кто использует фоновые задачи.

Резюмируя: вполне обычная ситуация

Автозапуск: Receiver для автозапуска при включении устройства

Пусть вас не смущает, что вы уже видели это выше. Выше было разрешение на получение этого бродкаста, а тут уже сам получатель (ресивер). И автор переживает, что у него три типа:

BootCompletedReceiver с тремя разными действиями (BOOTCOMPLETED, QUICKBOOTPOWERON) — это гарантирует, что запуск выполниться автоматически при любой возможности сразу после включения телефона, даже до его разблокировки.

Рис. 29

Но на самом деле всё просто. Работает реально только первый тип. Второй давно никто не может получить (можно сказать, что его не существует), а третий так вообще только БЫЛ КОГДА-ТО у HTC. То есть второй и третий — это хвосты ТамТама.

Вот, кстати, код целиком:

        <receiver
            android:name="ru.ok.tamtam.android.services.BootCompletedReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
                <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
        </receiver>

Предлагаю VK пересмотреть android:exported="true". Экшен android.intent.action.BOOT_COMPLETED кроме системы никто послать не может, а два других уже давно сдохли. Думаю, имеет смысл выставить в false этот параметр.

Резюмируя: частично устаревший код. Будет исправлен в будущем.

Заключение исследователя

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

Не выявил

Однако нашлось и множество «спорных» возможностей, которые выходят далеко за рамки обычных возможностей мессенджера

Не нашлось

Автозапуск при загрузке, скрытые загрузки, отключение резервного копирования и сложность анализа кода (extractNativeLibs=“false”) — это приемы, которые чаще ассоциируются с вредоносным ПО, стремящимся закрепиться в системе и скрыть свою деятельность.

Нет

В итоге, перед нами не просто мессенджер, а многофункциональный комплекс с широчайшими полномочиями.

Перед нами типичный современный мессенджер с очень плохим GUI, не соответствующим Android.

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

Опустим пафос в начале и остановимся на “наблюдать через камеру”. Важно понимать, что Камера и Микрофон НЕДОСТУПНЫ приложениям в фоне. Скрыто их запускать нельзя. Вы обязаны хотя бы держать сервис переднего плана, который обязан создавать уведомление. А ещё Android нарисует индикатор использования камеры или микрофона.