Как работает Магиск?

Magisk известен как «бессистемный» корневой метод. По сути, это способ изменить систему, фактически не изменяя ее. Изменения безопасно хранятся в загрузочном разделе, а не в реальных системных файлах.

Я осмотрелся, но не нашел достаточного объяснения того, как это на самом деле работает. Как получить и поддерживать root-доступ? Какова именно роль загрузочного раздела и если он интегрируется с системным разделом, как он это делает?

Действительно подробное описание того, как это работает, отсутствует везде, где я искал, поэтому я был бы очень признателен.

Ответы (2)

Большая часть вашего вопроса освещена в документации Magisk . Я процитирую один из моих предыдущих ответов на другой вопрос с некоторыми ненужными подробностями :)

ПРЕДПОСЫЛКИ:

Чтобы иметь полное представление о том, как работает Magisk, необходимо иметь базовое представление о:

  • Дискреционный контроль доступа ( DAC )
  • Идентификаторы пользователей ( [ESR]UID),set-user-ID
  • Возможности Linux (процесс и файл), обеспечивающие детальный контроль над разрешениями суперпользователя.
  • Обязательный контроль доступа ( MAC )
  • SELinux на Android
  • Пространства имен монтирования, использование Android пространств имен для разрешений на хранение
  • Привязать крепление
  • Процесс загрузки Android, разделы и файловые системы
  • Службы Android init(самый первый процесс, запущенный ядром)
  • *.rc файлы
  • Структура bootраздела (ядро + DTB + виртуальный диск), BLOB-объекты дерева устройств , DM-Verity ( проверенная загрузка Android ), полное шифрование диска / шифрование на основе файлов ( FDE/FBE ) и т. д.

ЧТО ТАКОЕ КОРЕНЬ?

Получение привилегий root означает запуск процесса (обычно оболочки) с нулевым UID (0) и всеми возможностями Linux, чтобы привилегированный процесс мог обойти все проверки разрешений ядра.
Привилегии суперпользователя обычно получаются путем выполнения бинарного файла, который имеет:

Именно так suи sudoработают на Linux в традиционных UNIX DAC. Непривилегированные пользователи запускают эти двоичные файлы для получения прав root.

Это менее распространенный метод.

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

КАК ANDROID ОГРАНИЧИВАЕТ ROOT-ДОСТУП?

До Android 4.3 можно было просто запустить set-user-ID-root suдвоичный файл, чтобы повысить его разрешения до пользователя root. Однако в Android 4.3 было несколько улучшений безопасности , которые нарушили это поведение:

  • Android переключился на файловые возможности вместо того, чтобы полагаться на set-user-IDтипы уязвимостей безопасности. Более безопасный механизм: возможности Ambient также были представлены в Android Oreo.
  • Системные демоны и службы могут использовать возможности файлов для получения возможностей процесса (см. раздел Преобразование возможностей во время execve ), но приложения также не могут этого сделать, потому что код приложения выполняется с помощью zygoteатрибута управления процессом NO_NEW_PRIVS, игнорируя, set-user-IDа также возможности файла. SUID также игнорируется при монтировании /systemи /dataс nosuidопцией для всех приложений.
  • UID можно переключить, только если вызывающий процесс имеет возможность SETUID/SETGID в своем ограничивающем наборе. Но приложения для Android созданы для работы со всеми возможностями, уже реализованными во всех наборах с использованием атрибута управления процессом CAPBSET_DROP.
  • Начиная с Oreo, возможность приложений изменять UID/GID была дополнительно подавлена ​​за счет блокировки определенных системных вызовов с помощью фильтров seccomp .

Так как автономные suбинарники перестали работать с выходом Jelly Bean, был сделан переход в режим su daemon . Этот демон запускается во время загрузки и обрабатывает все запросы суперпользователя, сделанные приложениями, когда они выполняют специальный suдвоичный файл ( 1 ) . install-recovery.sh(расположенный под /system/bin/или /system/etc/), который выполняется предустановленной службой инициализации flash_recovery(бесполезна для авантюристов; восстановление обновлений после установки OTA), использовался для запуска этого демона SU при загрузке.

Следующая серьезная проблема возникла, когда SELinux был установлен строго enforcingс выпуском Android 5.0. Служба flash_recovery была добавлена ​​в ограниченный контекст SELinux : u:r:install_recovery:s0что остановило неподдельный доступ к системе. Даже UID 0 должен был выполнять очень ограниченный набор задач на устройстве. Таким образом, единственным жизнеспособным вариантом было запустить новую службу с неограниченным SUPER CONTEXT , исправив политику SELinux. Это то, что было сделано (временно для Lollipop ( 2 , 3 ) , а затем навсегда для Marshmallow), и это то, что делает Magisk.

КАК РАБОТАЕТ МАГИСК?

Для перепрошивки Magisk обычно требуется устройство с разблокированным загрузчиком, чтобы его boot.imgможно было динамически модифицировать из пользовательского восстановления ( 4 ) или предварительно модифицированного boot.img ( 5 ), которое можно было прошить / загрузить, например, из fastboot.
В качестве примечания: можно запустить Magisk на работающем ПЗУ, если вы каким-то образом получите привилегии root, используя какой-либо эксплойт в ОС ( 6 ) . Однако большинство таких уязвимостей безопасности было устранено с течением времени ( 7 ) .
Также из-за некоторых уязвимостей на уровне SoC (таких как режим EDL от Qualcomm ) заблокированный загрузчик может быть взломан для загрузки модифицированного образа загрузки/восстановления, нарушающегоЦепочка доверия . Однако это лишь исключения.

Как только устройство загружается из patched boot.img, полностью привилегированный демон Magisk (с UID: 0, полными возможностями и неограниченным контекстом SELinux) запускается с самого начала процесса загрузки. Когда приложению требуется root-доступ, оно запускает двоичный файл Magisk (/sbin/)su(доступный через DAC и MAC ), который не меняет UID/GID сам по себе, а просто подключается к демону через сокет UNIX ( 8 ) и запрашивает запрос приложение корневая оболочка со всеми возможностями. Чтобы взаимодействовать с пользователем для предоставления/отклонения suзапросов от приложений, демон подключается к Magisk Managerприложению, которое может отображать подсказки пользовательского интерфейса. База данных ( /data/adb/magisk.db) предоставленных/отклоненных разрешений создается демоном для будущего использования.

Процесс загрузки:
ядро ​​Android запускается initв permissiveрежиме SELinux при загрузке (за некоторыми исключениями ). initзагружает /sepolicy(или разделяет политику ) перед запуском любых служб/демонов/процессов, устанавливает их enforcingи затем переключается на свой собственный контекст. Отсюда после этого даже initполитика не позволяет вернуться в разрешающий режим ( 9 , 10 ) . Ни одна из этих политик не может быть изменена даже пользователем root ( 11 ) . Поэтому Magisk заменяет /initфайл кастомным init, который исправляет правила политики SELinux с помощью SUPER CONTEXT ( u:r:magisk:s0) и определяетservice для запуска демона Magisk с этим контекстом. initЗатем выполняется оригинал для продолжения процесса загрузки ( 12 ) .

Бессистемная работа:
поскольку initфайл встроен в boot.img, его изменение неизбежно, и /systemизменение становится ненужным. Вот где systemlessбыл придуман этот термин ( 13 , 14 ) . Основная забота заключалась в том, чтобы упростить OTA — перепрошивка bootобраза (и восстановление) доставляет меньше хлопот, чем перепрошивкаsystem . Блочная OTA для измененного /systemраздела не будет работать, поскольку она позволяет использовать dm-verityкриптографическую подпись systemраздела .

Система от имени пользователя root:
на более новых устройствах, использующих систему от имени пользователя root, ядро ​​загружается не ramdiskиз . Так что нужно заменить на Magisk . Также Magisk модифицирует и размещает свои файлы в и . Это означает , что его нужно изменить, но подход Magisk заключается в том, чтобы не трогать раздел.bootsystem[system.img]/initinit/init.rc/root/sbinsystem.imgsystem

На A/Bустройствах во время обычной загрузки skip_initramfsпараметр передается из загрузчика в командную строку ядра, как boot.imgуказано ramdiskдля восстановления. Таким образом, Magisk исправляет двоичный файл ядра, чтобы он всегда игнорировал skip_initramfsзагрузку при восстановлении, и помещает initдвоичный файл Magisk в восстановление ramdiskвнутри файла boot.img. При загрузке, когда ядро ​​​​загружается для восстановления, если нет skip_initramfsпользователя, который намеренно загрузился для восстановления, тогда Magisk initпросто выполняет recovery init. В противном случае system.imgмонтируется в /system_rootMagisk init, затем содержимое ramdiskкопируется для /очистки всего ранее существовавшего, файлы добавляются / изменяются в rootfs /, /system_root/systemмонтируется привязкой к /system, и, наконец, [/system]/initвыполняется (15 , 16 ) .

Однако с Q все снова изменилось, теперь /systemон монтируется в , /но файлы, которые нужно добавить/изменить, похожи на /init, /init.rcи /sbinперекрываются монтированием привязки ( 17 ) .

На non-A/B system-as-rootустройствах необходимо установить Magisk для восстановления ramdisk, чтобы сохранить бессистемный подход, поскольку boot.imgон не содержит ramdisk ( 18 ) .

Модули:
Дополнительным преимуществом systemlessподхода является использование Magisk Modules. Если вы хотите поместить некоторые двоичные файлы в /system/*bin/или изменить некоторые файлы конфигурации (например, hostsили dnsmasq.conf) или некоторые файлы библиотек / фреймворков (например, требуемые модами, такими как XPOSED) в /systemили /vendor, вы можете сделать это, фактически не касаясь раздела, используя Magic Mount ( на основе креплений биндов). Magisk поддерживает добавление и удаление файлов путем их наложения.

MagiskHide: ( 19 )
Еще одна проблема заключалась в том, чтобы скрыть присутствие Magisk, чтобы приложения не могли узнать, рутировано ли устройство. Многим приложениям не нравятся рутированные устройства, и они могут перестать работать. Google был одним из основных пострадавших, поэтому они представили SafetyNet как часть Play Protect , которая работает как процесс GMS (Play Services) и сообщает приложениям (включая их собственные Google Pay) и, следовательно, их разработчикам, что устройство в настоящее время находится в незащищенном состоянии. состояние ( 20 ) .

Укоренение — это одно из многих возможных закаленных состояний, другие — непроверенная загрузка, разблокированный загрузчик, отсутствие сертификации CTS, пользовательское ПЗУ, отлаживаемая сборка, permissiveSELinux, включенный ADB, некоторые плохие свойства, наличие Lucky Patcher, Xposed и т. д. Magisk использует некоторые приемы, чтобы убедиться, что большинство этих тестов всегда проходят, хотя приложения могут использовать другие API Android или напрямую читать некоторые файлы. Некоторые модули обеспечивают дополнительную обфускацию.

Помимо сокрытия своего присутствия от Google SafeyNet, Magisk также позволяет пользователям скрывать root ( suдвоичные и любые другие файлы, связанные с Magisk) от любого приложения, опять же используя привязку монтирования и пространства имен монтирования. Для этого zygoteнеобходимо постоянно следить за виртуальными машинами недавно разветвленных приложений.

Однако действительно сложно скрыть рутированное устройство от приложений, поскольку развиваются новые методы обнаружения присутствия Magisk, в основном из /procили других файловых систем. Таким образом , делается ряд причуд, чтобы должным образом поддерживать скрытие модификаций от обнаружения . Magisk пытается удалить все следы своего присутствия в процессе загрузки ( 21 ) .


Magisk также поддерживает:

  • Отключениеdm-verity и /dataшифрование путем модификации fstabramdisk, /vendorили DTB). См. Как отключить dm-verity на Android?
  • Изменение свойств только для чтения с помощью инструмента resetprop , изменениеboot.img с помощью magiskboot и изменение политики SELinux с помощью magiskpolicy .
  • Выполнение загрузочных скриптов с использованием init.d-подобного механизма ( 22 ) .

Это краткое описание функций Magisk, предлагаемых в настоящее время (AFAIK).


ДАЛЬНЕЙШЕЕ ЧТЕНИЕ:

Это один из самых хорошо написанных ответов, которые я когда-либо читал здесь. Только одно: что вы подразумеваете под «устройствами A/B»? Объясняется ли этот термин в одной из предыдущих ссылок?
У устройств @SteffenWinkler A/B есть 2 слота разделов для загрузки: source.android.com/devices/tech/ota/ab
Очаровательный! Ваша первая ссылка должна была быть здесь?: topjohnwu.github.io/Magisk/details.html

Magisk предоставляет root-доступ, предоставляя рабочий «корневой» двоичный файл, смонтированный в /sbin/magisk. Любое приложение, которое попытается запустить этот двоичный файл, вызовет Magisk, чтобы предоставить им root-доступ, который, в свою очередь, управляется и поддерживается приложением Magisk Manager.

Раздел /boot— это отдельный раздел, в котором хранятся некоторые данные, необходимые для загрузки системы. Он включает в себя инициализацию некоторых очень низкоуровневых механизмов, таких как ядро ​​Linux, драйверы устройств, файловые системы и т. д., до запуска ОС Android верхнего уровня. Он разделен таким образом, что в нем хранятся данные уровня Linux, а данные уровня Android (SystemUI, настройки и т. д.) хранятся в разделе /system. Изменение /bootне считается изменением/system , последнее из которых обычно проверяется DM-verity и AVB.

И Magisk исправляет и интегрируется в раздел/boot , поэтому он вообще не касается системного раздела. Он использует технику, называемую «монтирование привязки» , для изменения содержимого системных файлов, которые видят другие программы, без фактического изменения базовой файловой системы под системным разделом (поэтому «настоящие» файлы остаются нетронутыми).