¿Cómo funciona Magisk?

Magisk es conocido como un método raíz "sin sistema". Es esencialmente una forma de modificar el sistema sin modificarlo realmente. Las modificaciones se almacenan de forma segura en la partición de arranque en lugar de modificar los archivos reales del sistema.

He buscado pero no encontré una explicación suficiente sobre cómo funciona realmente. ¿Cómo se obtiene y mantiene el acceso raíz? ¿Cuál es exactamente la función de la partición de arranque y, si se integra con la partición del sistema, cómo lo hace?

En todos los lugares donde busqué falta una descripción realmente detallada de cómo funciona, por lo que sería muy apreciada.

Respuestas (2)

La mayor parte de su pregunta está cubierta en la documentación de Magisk . Citaré una de mis respuestas anteriores a una pregunta diferente, con algunos detalles innecesarios :)

PRERREQUISITOS:

Para tener una comprensión completa de cómo funciona Magisk, uno debe tener una comprensión básica de:

  • Control de acceso discrecional ( DAC )
  • Identificadores de usuario ( [ESR]UID),set-user-ID
  • Capacidades de Linux (proceso y archivo) que proporcionan un control detallado sobre los permisos de superusuario
  • Control de Acceso Obligatorio ( MAC )
  • SELinux en Android
  • Montar espacios de nombres, uso de Android de espacios de nombres para permisos de almacenamiento
  • Montaje de enlace
  • Proceso de arranque, particiones y sistemas de archivos de Android
  • Servicios de Android init(el primer proceso iniciado por kernel)
  • archivos *.rc
  • Estructura de bootla partición (kernel + DTB + ramdisk), Device Tree Blobs , DM-Verity ( Android Verified Boot ), Full Disk Encryption / File Based Encryption ( FDE/FBE ), etc.

¿QUÉ ES LA RAÍZ?

Obtener privilegios de root significa ejecutar un proceso (generalmente shell) con UID cero (0) y todas las capacidades de Linux para que el proceso privilegiado pueda omitir todas las verificaciones de permisos del kernel.
Los privilegios de superusuario generalmente se obtienen al ejecutar un binario que tiene:

Así es como funciona suy sudofunciona en Linux en UNIX DAC tradicional. Los usuarios sin privilegios ejecutan estos binarios para obtener derechos de root.

Este es el método menos común utilizado.

En ambos casos, el proceso de llamada debe tener todas las capacidades en su Bounding Set (una de las 5 categorías de capacidades que puede tener un proceso) para tener privilegios de root reales.

¿CÓMO ANDROID RESTRINGE EL ACCESO A LA RAÍZ?

Hasta Android 4.3, uno podría simplemente ejecutar un set-user-ID-root subinario para elevar sus permisos al usuario root. Sin embargo, hubo una serie de mejoras de seguridad en Android 4.3 que interrumpieron este comportamiento:

  • Android cambió a capacidades de archivo en lugar de confiar en el set-user-IDtipo de vulnerabilidades de seguridad. Un mecanismo más seguro: las capacidades ambientales también se han introducido en Android Oreo.
  • Los demonios y servicios del sistema pueden hacer uso de las capacidades de archivo para obtener capacidades de proceso (consulte la sección Transformación de capacidades durante la ejecución ), pero las aplicaciones tampoco pueden hacerlo porque el código de la aplicación se ejecuta con el zygoteatributo de control de proceso NO_NEW_PRIVS, ignorando set-user-IDasí como las capacidades de archivo. SUID también se ignora al montar /systemy /datacon nosuidopción para todas las aplicaciones.
  • El UID se puede cambiar solo si el proceso de llamada tiene capacidad SETUID/SETGID en su conjunto de delimitación. Pero las aplicaciones de Android están diseñadas para ejecutarse con todas las capacidades ya eliminadas en todos los conjuntos utilizando el atributo de control de procesos CAPBSET_DROP.
  • A partir de Oreo, la capacidad de las aplicaciones para cambiar UID/GID se ha suprimido aún más mediante el bloqueo de ciertas llamadas al sistema mediante filtros seccomp .

Dado que los subinarios independientes dejaron de funcionar con el lanzamiento de Jelly Bean, se realizó una transición al modo su daemon . Este demonio se inicia durante el arranque y maneja todas las solicitudes de superusuario realizadas por las aplicaciones cuando ejecutan el subinario especial ( 1 ) . install-recovery.sh(ubicado debajo /system/bin/de o /system/etc/) que se ejecuta mediante un servicio de inicio preinstalado flash_recovery(inútil para los aventureros; actualiza la recuperación después de una instalación OTA) se usó para iniciar este demonio SU en el arranque.

El siguiente gran desafío se enfrentó cuando SELinux se configuró estrictamente enforcingcon el lanzamiento de Android 5.0. El servicio flash_recovery se agregó a un contexto SELinux restringido : u:r:install_recovery:s0lo que detuvo el acceso no adulterado al sistema. Incluso el UID 0 estaba obligado a realizar un conjunto muy limitado de tareas en el dispositivo. Entonces, la única opción viable era comenzar un nuevo servicio con SUPER CONTEXT sin restricciones parcheando la política de SELinux. Eso es lo que se hizo (temporalmente para Lollipop ( 2 , 3 ) y luego permanentemente para Marshmallow) y eso es lo que hace Magisk.

¿CÓMO FUNCIONA MAGISK?

La actualización de Magisk generalmente requiere un dispositivo con el cargador de arranque desbloqueado para que boot.imgpueda modificarse dinámicamente desde la recuperación personalizada ( 4 ) o una modificación previa boot.img ( 5 ) podría actualizarse / iniciarse, por ejemplo, desde fastboot.
Como nota al margen, es posible iniciar Magisk en una ROM en ejecución si de alguna manera obtiene privilegios de root utilizando algún exploit en el sistema operativo ( 6 ) . Sin embargo, la mayoría de estas vulnerabilidades de seguridad se han solucionado con el tiempo ( 7 ) .
Además, debido a algunas vulnerabilidades en el nivel de SoC (como el modo EDL de Qualcomm ), el gestor de arranque bloqueado se puede piratear para cargar una imagen de arranque/recuperación modificada rompiendo elCadena de Confianza . Sin embargo, estas son solo excepciones.

Una vez que el dispositivo arranca desde parcheado boot.img, un demonio Magisk con todos los privilegios (con UID: 0, capacidades completas y contexto SELinux sin restricciones) se ejecuta desde el comienzo del proceso de arranque. Cuando una aplicación necesita acceso a la raíz, ejecuta (/sbin/)suel binario de Magisk (accesible mundialmente por DAC y MAC ) que no cambia el UID/GID por sí solo, sino que simplemente se conecta al daemon a través de un socket UNIX ( 8 ) y solicita proporcionar la solicitud. app un shell raíz con todas las capacidades. Para interactuar con el usuario para otorgar/denegar susolicitudes de aplicaciones, el daemon está conectado con la Magisk Manageraplicación que puede mostrar indicaciones de la interfaz de usuario. /data/adb/magisk.dbEl daemon crea una base de datos ( ) de permisos otorgados/denegados para uso futuro.

Proceso de arranque:
el kernel de Android comienza initcon SELinux en permissivemodo de arranque (con algunas excepciones ). initcarga /sepolicy(o divide la política ) antes de iniciar cualquier servicio/demonio/proceso, lo establece enforcingy luego cambia a su propio contexto. A partir de aquí, initla política ni siquiera permite volver al modo permisivo ( 9 , 10 ) . Tampoco la política puede ser modificada ni siquiera por el usuario root ( 11 ) . Por lo tanto, Magisk reemplaza /initel archivo con un personalizado initque parchea las reglas de la política de SELinux con SUPER CONTEXT ( u:r:magisk:s0) y define elservicio para lanzar Magisk daemon con este contexto. Luego se ejecuta el original initpara continuar con el proceso de arranque ( 12 ) .

Trabajo sin sistema:
dado que el initarchivo está integrado boot.img, es inevitable modificarlo y /systemla modificación se vuelve innecesaria. Ahí es donde systemlessse acuñó el término ( 13 , 14 ) . La principal preocupación era hacer que las OTA fueran más fáciles: volver a flashear la bootimagen (y la recuperación) es menos complicado que volver a flashearsystem . La OTA basada en bloques en una /systempartición modificada fallará porque permite el uso de dm-veritypara firmar criptográficamente la systempartición .

System-as-root:
en los dispositivos más nuevos que usan system-as-root, el kernel no se carga ramdiskdesde bootsino desde system. Por lo tanto [system.img]/init, debe ser reemplazado por el de Magisk init. Además, Magisk modifica /init.rcy coloca sus propios archivos en /rootformato y /sbin. Significa system.imgque se modificará, pero el enfoque de Magisk es no tocar systemla partición.

En A/Blos dispositivos durante el arranque normal, skip_initramfsla opción se pasa desde el gestor de arranque en la línea de comandos del kernel como boot.imgcontenido ramdiskpara la recuperación. Por lo tanto, Magisk parchea el binario del kernel para ignorar siempre, es skip_initramfsdecir, el arranque en recuperación, y coloca initel binario de Magisk en recuperación ramdiskdentro de boot.img. En el arranque, cuando el kernel arranca en recuperación, si no hay skip_initramfsun usuario intencionadamente arrancado en recuperación, entonces Magisk initsimplemente ejecuta recovery init. De lo contrario , Magisk system.imglo monta en , los contenidos de se copian para limpiar todo lo que existía anteriormente, los archivos se agregan/modifican en rootfs , se enlazan y finalmente se ejecutan (/system_rootinitramdisk///system_root/system/system[/system]/init15 , 16 ) .

Sin embargo, las cosas han vuelto a cambiar con Q, ahora /systemse monta en /pero los archivos que se agregarán/modificarán como /init, /init.rcy /sbinse superpondrán con montajes de enlace ( 17 ) .

En non-A/B system-as-rootlos dispositivos, Magisk debe instalarse en la recuperación ramdiskpara mantener el enfoque sin sistema porque boot.imgno contiene ramdisk ( 18 ) .

Módulos:
un beneficio adicional del systemlessenfoque es el uso de Magisk Modules. Si desea colocar algunos archivos binarios debajo /system/*bin/o modificar algunos archivos de configuración (como hostso dnsmasq.conf) o algunas bibliotecas/archivos de marco (como los requeridos por mods como XPOSED) en /systemo /vendor, puede hacerlo sin tocar la partición utilizando Magic Mount ( basado en montajes de enlace). Magisk admite agregar y eliminar archivos superponiéndolos.

MagiskHide: ( 19 )
Otro desafío fue ocultar la presencia de Magisk para que las aplicaciones no puedan saber si el dispositivo está rooteado. A muchas aplicaciones no les gustan los dispositivos rooteados y pueden dejar de funcionar. Google fue uno de los principales afectados, por lo que introdujeron SafetyNet como parte de Play Protect , que se ejecuta como un proceso GMS (Play Services) y les dice a las aplicaciones (incluidas las propias Google Pay) y, por lo tanto, a sus desarrolladores que el dispositivo se encuentra actualmente en un estado no manipulado. estado ( 20 ) .

El enraizamiento es uno de los muchos estados moderados posibles, otros son Arranque no verificado, cargador de arranque desbloqueado, no certificación CTS, ROM personalizada, compilación depurable, permissiveSELinux, ADB activado, algunas propiedades malas , presencia de Lucky Patcher, Xposed, etc. Magisk usa algunos trucos para asegurarse de que la mayoría de estas pruebas siempre pasen, aunque las aplicaciones pueden usar otras API de Android o leer algunos archivos directamente. Algunos módulos proporcionan ofuscación adicional.

Además de ocultar su presencia de SafeyNet de Google, Magisk también permite a los usuarios ocultar la raíz ( suarchivos binarios y cualquier otro archivo relacionado con Magisk) de cualquier aplicación, nuevamente utilizando montajes de enlace y espacios de nombres de montaje. Para esto, zygotedebe vigilarse continuamente las máquinas virtuales de las aplicaciones recién bifurcadas.

Sin embargo, es una tarea difícil ocultar realmente el dispositivo rooteado de las aplicaciones a medida que evolucionan las nuevas técnicas para detectar la presencia de Magisk, principalmente de /procu otros sistemas de archivos. Por lo tanto , se realizan una serie de peculiaridades para respaldar adecuadamente la ocultación de modificaciones de la detección . Magisk intenta eliminar todo rastro de su presencia durante el proceso de arranque ( 21 ) .


Magisk también admite:

  • Desactivacióndm-verity y /datacifrado modificando fstab(en ramdisk, /vendoro DTB). Consulte ¿Cómo deshabilitar dm-verity en Android?
  • Cambio de propiedades de solo lectura con la herramienta resetprop , Modificaciónboot.img con magiskboot y Modificación de la política de SELinux con magiskpolicy .
  • Ejecución de scripts de arranque usando init.dun mecanismo similar ( 22 ) .

Esa es una breve descripción de las funciones que Magisk ofrece actualmente (AFAIK).


OTRAS LECTURAS:

Esta es una de las respuestas mejor escritas que he leído aquí. Solo una cosa: ¿Qué quieres decir con 'dispositivos A/B'? ¿Ese término está explicado en alguno de los enlaces anteriores?
Los dispositivos @SteffenWinkler A/B tienen 2 ranuras de partición para arrancar desde: source.android.com/devices/tech/ota/ab
¡Fascinante! ¿Tu primer enlace estaba destinado a estar aquí?: topjohnwu.github.io/Magisk/details.html

Magisk proporciona acceso a la raíz al proporcionar un binario "raíz" en funcionamiento montado en /sbin/magisk. Cualquier aplicación que intente ejecutar este binario abrirá Magisk para otorgarles acceso de root, que a su vez es administrado y mantenido por la aplicación Magisk Manager.

La /bootpartición es una partición separada que almacena algunos datos necesarios para iniciar el sistema. Incluye la inicialización de algunos mecanismos de muy bajo nivel, como el kernel de Linux, los controladores de dispositivos, los sistemas de archivos, etc., antes de que aparezca el sistema operativo Android de capa superior. Está separado de tal manera que las cosas de nivel de Linux se almacenan en él, mientras que las cosas de nivel de Android (SystemUI, Configuración, etc.) se almacenan en la /systempartición. Modificar /bootno cuenta como modificar/system , el último de los cuales es lo que DM-verity y AVB generalmente verifican.

Y Magisk se parchea y se integra en la /bootpartición , por lo que no toca la partición del sistema en absoluto. Utiliza una técnica llamada "un montaje de enlace" para cambiar el contenido de los archivos del sistema que ven otros programas, sin modificar realmente el sistema de archivos subyacente debajo de la partición del sistema (por lo que los archivos "reales" se dejan intactos).