• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Проходим все проверки безопасности на Android с Magisk

deu5n

floppy-диск
Пользователь
Регистрация
20.09.2025
Сообщения
9
Реакции
9
Было ли у вас такое, что, например, банк или какое-нибудь государственное приложение отказывается запускаться на вашем устройстве с Root из соображений безопасности? Лично у меня да, причём застало это меня в самый неудачный момент - в очереди. Можно было бы сказать, что тогда я поклялся обходить все проверки на Root, но мы тут не трагикомедию разводим. Разберём конкретно, как приложения могут определять Root и как их обмануть.

Сразу определимся с тестовым аппаратом - смартфон неназванной модели, в качестве системы стоит неофициальный LineageOS 21 (A14) с установленными GApps и Magisk, в качестве рекавери - TWRP 3.7.1. Не самое мощное устройство - на борту печально известный (для юзеров бюджеток) Helio G99 и 4GB ОЗУ. Короче говоря, бюджетный вариант, который нынче всё ещё годится для потребления медиа-контента.
1. Наличие приложений для Root. Да, банально и просто - проверяется список установленных приложений на устройстве (а для этого не нужны разрешения), и если есть Magisk/KernelSU/любое другое приложение для Root, то приложение отказывается запускаться. Реализуется очень легко, работает очень легко и обходится очень легко - достаточно просто поменять имя пакета (ну или поставить модуль).
Вспоминая про то самое приложение, которое тогда не пустило меня, оно работает по тому же принципу =) Можно убедиться в этом, закинув его в декомпилятор:
1.png
2.png
3.png


Интересно, что оно ещё детектит приложения для взлома
2. Play Integrity API. Это API, разработанное Google, которое позволяет разработчикам приложений проверять подлинность приложений И устройства. Данный способ уже более надёжный, поскольку не обходится обычным скрытием установленного приложения. Сервисы Google проверяют телефон и выставляют "вердикт". Есть несколько вердиктов, нужный для прохода проверки - минимум MEETS_DEVICE_INTEGRITY (или у бывал прошивочных форумов - "2 галочки"). Система с одной стороны универсальная, с другой создаёт единую точку "отказа", которая конечно же "откажет" после того, как вы установите волшебный модуль (но об этом позже).
3. Свойства Android. Через них можно узнать много вещей: от хеш-сумм системных разделов до фингерпринта прошивки (коднейм устройства, точная версия Android и прошивки и т.д.). Если говорить о нашем вопросе, то через них можно узнать разблокирован ли загрузчик или целы ли разделы системы, отвечающие за шифрование.
4. Отдельные следы Root. Наверное все приложения для Root при стандартных настройках оставляют следы в системе - странные маунты, файлы и т.п. То же самое касается и кастомных прошивок - их тоже могут детектить, причём даже легче, по тем же свойствам. Делается это банально из логики: на устройстве стоит кастомная прошивка => на устройстве разблокирован загрузчик => устройство не безопасно.
Стоит понимать, что на практике зачастую встречаются 1 и 2 способ, иногда 3 для проверки целостности загрузчика. 4 способ скорее всего встречается в софте для проверки скрытости Root.

Теперь, давайте сделаем замеры перед забегом:
4.jpg
5.jpg
В Android все приложения запускаются от единого системного процесса - zygote. Сделано это с целью оптимизации (поскольку zygote подгружает все необходимые библиотеки заранее). Если управлять zygote, то можно манипулировать любыми приложениями как угодно. Для этой цели и был создан Zygisk - уже встроенный модуль Magisk. Однако мы рассмотрим его брата - Zygisk Next. Это реализация Zygisk с нуля, отдельно от Magisk, благодаря чему его можно использовать ещё в KernelSU и APatch. В нашем случае мы воспользуемся им, поскольку он оставляет меньше следов инжекта, по сравнению с встроенным Zygisk.

Установка Zygisk Next (как и любого модуля в Magisk) проста: скачиваем модуль (Github: Dr-TSNG/ZygiskNext), заходим в Magisk, затем во вкладку "Modules" и нажимаем на "Install from storage". Откроется файловый менеджер, находим модуль и устанавливаем, после чего перезагружаемся.

Теперь Zygisk Next нужно настроить, но модуль всё-таки больше заточен под KernelSU и конфигурация там происходит через Web UI, который в Magisk не предусмотрен. Не отчаиваемся, а устанавливаем Standalone APK для работы с Web UI — поддерживаемую реализацию WebUI X (Github: MMRLApp/WebUI-X-Portable). Запускаем приложение и видим наш модуль, нажимаем и переходим в настройки.
6.jpg
Переключаем Denylist Policy на Enforced (т.е. включаем Denylist) и включаем "Use anonymous memory" (некоторые механизмы детекта не будут ругаться). Теперь надо разобраться, что такое Denylist - это список процессов приложений, к которым не будут применяться какие-либо инжекты через Zygisk. Очевидно, сюда добавляются чувствительные приложения, которые в наглую не поинжектишь.

А теперь настройка списка: при установке через Magisk, Zygisk Next будет брать Denylist из настроек самого Magisk. Для этого перейдите в Magisk, затем в настройки и найдите "Configure Denylist". Нажав на кнопку, вы попадёте в меню, где вольны сами выбирать приложения или отдельные их процессы. Важно: в настройках Magisk пункты "Zygisk" и "Enforce Denylist" должны быть отключены! Данную задачу берёт на себя модуль Zygisk Next. Также вместо точечной настройки Denylist, можно использовать настройку Zygisk Next - "Treat non-root apps as denylist" (все приложения без Root будут в Denylist), но учтите, что приложение, которому нужен Root, но оно ещё не имеет доступа (например, ещё не запускалось), не увидит Root вовсе и не запустится.

Теперь перейдём к установке Zygisk Assistant. Данный модуль скрывает для процессов из Denylist следы Root и в целом модификации на более глубоком уровне (подозрительные маунты, статус загрузчика и т.п.). Устанавливается, как и Zygisk Next - скачиваем (Github: snake-4/Zygisk-Assistant), закидываем в модули Magisk, перезагружаемся. На этом с данным модулем покончено.

Следующая остановка - LSPosed. Это фреймворк на базе Zygisk/Riru, который позволяет хукать функции в приложениях и системе, без, логично, модификации оных. Грубо говоря, LSPosed позволяет создавать модули, действующие точечно. Буквально в следующем разделе мы начнём рассматривать их, но сначала установим LSPosed. Впрочем, процесс установки не сильно отличается от других модулей - скачать (Github: LSPosed/LSPosed), установить, перезапустить. После перезапуска в уведомлениях у вас появится уведомление от менеджера LSPosed. Если нет, можете попробовать ввести номер *#*#5776733#*#*, после чего менеджер должен открыться. При первом заходе вам будет предложено создать ярлык на рабочем столе (уведомление однако всё ещё будет, пока вы не выключите его в настройках), если вам так удобнее, то можете это сделать. Если у вас возникли проблемы с LSPosed, то можете попробовать проделать следующий алгоритм: удалить Zygisk Next и LSPosed, рестарт, поставить Zygisk Next, рестарт, поставить LSPosed, рестарт. Помните о золотом правиле рестарта после установки каждого нового расширения.

После всех этих манипуляций, список модулей в Magisk у вас должен выглядеть примерно так:
7.jpg
Решается данная проблема одним модулем в LSPosed - Hide My Applist. Откройте LSPosed Manager, перейдите во вкладку Repository (крайняя слева), найдите Hide My Applist. После скачивания и установки приложения, в LSPosed, в разделе Modules у вас появится соответствующий модуль. Перейдите в него, включите, больше ничего не трогая, и перезагрузите устройство, чтобы необходимый для работы Hide My Applist сервис запустился.

После рестарта устройства заходим в приложение, затем в раздел "App manage" и найдите приложение, от которого хотите скрыть Magisk. Нажмите на него, включите "Enable hide" и ниже под заголовком "Template config" найдите "0 additional apps invisible". Нажав на эту кнопку, вы сможете выбрать любые приложения, которые хотите скрыть от конкретно этого приложения. Если уж речь об Magisk, то скрываем его и на всякий случай сам Hide My Applist.
8.png
9.png

поскольку мы практикуемся, в качестве приложения выбран Root детектор =)
Теперь, приложение ни слуху ни духу о каком-то там Magisk. Также Hide My Applist поддерживает шаблоны для блек/вайтлистов. Единственный минус на мой взгляд - нельзя настроить вайтлист на применяемые приложения, чтобы никто, кроме определённых приложений, не видели Magisk или что-либо ещё.
Тут нам потребуется 3 модуля для Magisk: Play Integrity Fork (Github: osm0sis/PlayIntegrityFork, разработчик IntegrityBox настоятельно рекомендует скачать последнюю CI версию), Tricky Store (Github: 5ec1cff/TrickyStore, но учтите, что с версии 1.1.0 он имеет закрытый код) или FOSS альтернативу (Github: beakthoven/TrickyStoreOSS) и IntegrityBox (Github: MeowDump/Integrity-Box). ...

В большинстве случаев на этом всё. Можно проверить сертификацию и увидеть заветный MEETS_STRONG_INTEGRITY.

10.png
Когда я сам копался со всем этим, не поверил, что всё так легко. Но мы тут не верим в магию, давайте разберёмся, что произошло:

IntegrityBox - это модуль из разряда "и швец, и жнец, и на дуде игрец". Оно само подгрузило рабочий keybox.xml, закинуло его в Tricky Store, а больше от нас ничего бы и не требовалось. Но стоп, что за keybox.xml? Это файлик, в котором хранятся цепочки сертификатов и приватные ключи, которые и используются при проверке подлинности устройства. Если Google отозвал один из сертификатов или ключей, то MEETS_STRONG_INTEGRITY мы никогда не получим. Если я верно понимаю, то разработчик IntegrityBox как раз занимается дампами, поэтому в модуле подгружаются актуальные keybox.xml. Этот модуль ещё поможет нам в следующих разделах.

Если у вас не появился STRONG вердикт (или со временем отпал), то можно сделать следующее: зайдите в WebUI X, найдите IntegrityBox, в подразделе Tricky Store нажмите на кнопку Update Keybox. Модуль загрузит новый keybox.xml и применит его. Также можете попробовать перейти в настройки Play Integrity Fork (кнопка PIF Fork Settings в том же IntegrityBox) и включить все настройки из разряда "Spoof ..."
В 99.5% случаях вам уже хватит всего того, что мы сделали с телефоном. Однако, можно ещё рассмотреть отдельные случаи, которыми могут детектить Root. Оговорюсь сразу, что речь пойдёт не только про Root, но и другие функции, которые для приложения могут быть подозрительными.

vbmeta. vbmeta - это раздел, в котором хранятся хеши разделов, которые, обычно, являются read-only.

11.png

Несовпадение хешей грозит лишь предупреждением при запуске, однако некоторые предпочитают затирать раздел, чтобы этого не было. Приводит это к тому, что приложение на попытку получить свойство ro.boot.vbmeta.digest получит лишь молчание (а точнее, пустую строку). Для решения этого вопроса ничего устанавливать не придётся, достаточно открыть ранее IntegrityBox (я же говорил, что мы к нему вернёмся) и нажать на "Fix Abnormal Boot Hash", который позволит нам установить хеш для vbmeta.

12.png
Не уверен, что есть разница от того, какой хеш вы поставите, но можете поставить хеш со стоковой прошивки. После перезагрузки хеш несуществующей vbmeta будет на вашем устройстве.

Поддельная геолокация. Некоторые приложения могут просматривать, включено ли поддельная геолокация. Для такого случая есть LSPosed модуль XposedFakeLocation. Ставится легко: заходим в LSPosed, находим в поиске и ставим. После установки приложения - запускаем модуль в LSPosed менеджере и выбираем, для каких приложений скрывать факт использования поддельных геолок.

13.png

ADB. Приложения могут видеть, что у вас включён режим разработчика и дебаг (он же ADB) по сети или USB. Очевидно, что это скорее для анти-реверса, но если ваше приложение так делает, это можно контрить при помощи LSPosed модуля 'IAmNotADeveloper'. Устанавливаете, включаете и выбираете приложения, для которых необходимо это использовать. Разработчик предупреждает: не используйте этот модуль на системных приложениях, иначе это может привести к проблемам с загрузкой устройства.
LSPosed Framework - безусловная мощная вещь, которая упрощает тюнинг системы и/или приложений, но нужно понимать пару нюансов:

1. Хуки LSPosed увеличивают "пинг" ответа функции. Это фундаментальная проблема, которая решается лишь отключением LSPosed полностью. С другой стороны, приложения на практике не используют такой подход для обнаружения, из-за его косвенности. Данный момент видно лишь в различных детекторах Root и любых других модификаций системы, по типу Native Detector.
14.png

2. LSPosed игнорирует приложения из Denylist. Это вполне логично, поскольку LSPosed базируется на Zygisk, а Denylist работает на уровне Zygisk. Суть в том, что Zygisk Assistant подтирает следы Root как раз от приложений из Denylist. Следовательно, что делать, если нам нужно полностью скрыть Root от приложения и при этом точечно применить модуль LSPosed для чего-либо (например, для сокрытия факта использования поддельной геолоки)? Правильно - ничего. Либо вынести приложение из Denylist, что грозит детектом Zygisk, либо использовать system-wide альтернативы модулям (те, что используются на "System Framework", например, как Hide My Applist). На самом деле, проблема не так уж и мешает, в абсолютном большинстве случаев точечное вмешательство в приложение от LSPosed даже не требуется.
Если вы сделали всё, о чём написано в данной статье, то все свойства, которые могут вызвать подозрение у приложения, скорее всего уже подменены другими модулями. Иными словами, проблема решилась сама собой. Даже если у вас иначе, всегда можно отредактировать файл по пути /system/build.prop. На этом закрываем вопрос, даже не открывая.
Очень редкие экземпляры могут смотреть на следы кастомных прошивок. Если такое и происходит, то чаще всего с LineageOS и прошивками на её базе, поскольку это самая часто используемая прошивка, как минимум в качестве базы для другой. Можно ли законтрить такую проверку - зависит от её "глубины". Следов кастомной прошивки множество - от установленных приложений до свойств. Приложение может, например, смотреть на запущенные процессы:

15.png

Для решения такой проблемы сейчас, вероятно, нет соответствующего модуля. Но этот факт подталкивает на мысль, что в большинстве случаев приложения не детектят конкретно LineageOS или любую другую прошивку. Тем не менее, если вы с таким умудрились столкнуться, то можете попробовать зайти в IntegrityBox, перейти в Module Settings, включить "Spoof Lineage Props" и "Override Lineage Props", а затем молиться, что это сработает. Более комплексных готовых решений я предложить не могу.
Забег окончен. Давайте сверимся:

16.png

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

17.png
Тут всё выглядит куда лучше, всего два детекта: аномальное окружение и пробел в маунтах. Первое из-за задержек LSPosed, а вот второе сложно понять от чего (сурсов детектора не дали), но что-то явно связанное с маунтами. Поскольку в сети на эту тему 0 информации, смею предположить, что никто так не определяет Root или любые другие модификации системы по той же причине, что и задержки от LSPosed, это просто есть конкретно в этом детекторе =)

Итого у нас всего два косвенных детекта, на которые никто кроме детекторов (и то далеко не всех) не обращает внимание, а также полностью проходимая проверка от Play Integrity. Это ли не успех?

Можно спросить: а зачем это нужно? Чтобы доказать, что Root - не приговор, как стремится доказать, например, Google со своим Play Integrity API. Ну, и чтобы пошалить, подменяя то, что нельзя ¯\(ツ)/¯ Надеюсь, вам эта статья-гайд поможет не совершать моих ошибок, впервые открыв программу после рута, прямо в очереди.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх