iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Magisk内部实现原理
  • 138
分享到

Magisk内部实现原理

androidlinuxubuntu 2023-08-31 20:08:04 138人浏览 泡泡鱼
摘要

Android10以后,Android系统限制了System分区的修改,结果就是,即使你i是自己编译的Android系统,即使是有做高的root权限,你依然无法挂载System分区并对其内容进行修改

在这里插入图片描述

Android10以后,Android系统限制了System分区的修改,结果就是,即使你i是自己编译的Android系统,即使是有做高的root权限,你依然无法挂载System分区并对其内容进行修改,尽管网上有各种帖子说可以使用mount -o rw,remount /,但这并没有解决开发者的实际问题。这意味着传统的万能root出现局限性,为了解决这个问题MaGISk的作者Top John Wu推文中确认了这一问题,并确认了导致该问题的原因是谷歌在Android10以后引入了EXT4 共享块,而这个共享块和其他分区的区别在于根本没有可用空间的概念,所以也就没办法挂在为可读写。为了解决这个问题,Magisk团队发现可以重定向文件读取时的文件路径来实现修改的目的,这似乎和我们Hook有相似之处,而这个,被Top John Wu称为Systemless(无System分区)而由此概念引申出来的Root方案,也叫做systemless root。。

Magisk文件结构

Magisk系统包含上层的控制App以及下层的可执二进制文件以及一些相关配置或者数据文件。我们从底层往上层看会更容易明白Magisk的功能构成和架构思维。

首先,Magisk 会挂载一个tmpfs目录来存放一些临时数据。在Android11以下,这个目录时sbin,从 Android 11 开始,/sbin文件夹可能不存在,那么 Magisk 会在/dev下随机创建一个文件夹并将其作为Magisk的Root文件夹。

放在sbin或者dev下的原因是:/sbin或/dev目录非su权限不可读,因此第三方APP无法检测。

我们可以通过在adb shell下使用magisk --path打印当前Magisk使用的目录:

找到magisk目录

blueline:/ # magisk --path/dev/bNpnxq

文件列表

接下来我们看下这个目录下都有什么文件,以及如何解读这些文件;

blueline:/dev/bNpnxq # ls -altotal 720drwx------  3 root    root       200 2022-12-24 21:41 .drwxr-xr-x 24 root    root      6200 2022-12-25 01:40 ..drwxr-xr-x  8 root    root       180 2022-12-24 21:41 .magisklrwxrwxrwx  1 root    root        10 1970-02-17 10:04 magisk -> ./magisk64-rwxr-xr-x  1 root    root    154452 1970-02-17 10:04 magisk32-rwxr-xr-x  1 root    root    247168 1970-02-17 10:04 magisk64-rwxr-xr-x  1 u0_a206 u0_a206 328240 2022-12-24 21:41 magiskpolicylrwxrwxrwx  1 root    root         8 1970-02-17 10:04 resetprop -> ./magisklrwxrwxrwx  1 root    root         8 1970-02-17 10:04 su -> ./magisklrwxrwxrwx  1 root    root        14 1970-02-17 10:04 supolicy -> ./magiskpolicy

可以看到除了magiskpolicy以外,其他都属于root用户组。

下面的注释说得很清楚了,直接看代码就好了。

# 想要获取 Magisk 正在使用的当前Base文件夹,请使用命令 `magisk --path`。# 像 magisk、magiskinit 这样的二进制文件和所有指向小程序的符号链接都直接存储在这个路径中。 # 这意味着当这是 /sbin 时,这些二进制文件将直接位于 PATH 中。MAGISKBASE=$(magisk --path)# Magisk 内部文件MAGISKTMP=$MAGISKBASE/.magisk# Magisk 的 BusyBox 目录。 # 在此文件夹中存储 busybox 二进制文件和指向其所有小程序的符号链接。 # 此目录的任何用法已弃用,请直接调用 /data/adb/magisk/busybox 并使用 BusyBox 的 ASH 独立模式。# 将来会删除此路径的创建。$MAGISKTMP/busybox# /data/adb/modules 将mount在这里。 原始文件夹未被使用(由于 nosuid 挂载标志)。$MAGISKTMP/modules# 当前的 Magisk 安装配置$MAGISKTMP/config# 分区镜像# 应用在访问系统文件的时候会优先访问该目录下的文件,以达到狸猫换太子的目的# 例如 system,system_ext,vendor,data......$MAGISKTMP/mirror# Magisk 内部创建block设备来挂载镜像,和mirror对应,对应关系可通过ls -al列出$MAGISKTMP/block# Root 目录补丁文件# 位于 system-as-root 设备上,/ 不可写。# 所有预初始化补丁文件都放在这里并mount$MAGISKTMP/rootdir

下面是/dev/bNpnxq/.magisk/mirror列出的文件列表,对应block的设备节点

blueline:/dev/bNpnxq/.magisk/block # ls -altotal 0d--------- 2 root root      160 2022-12-24 21:41 .drwxr-xr-x 8 root root      180 2022-12-24 21:41 ..brw------- 1 root root 253,   8 2022-12-24 21:41 databrw------- 1 root root 259,   4 1970-02-17 10:04 metadatabrw------- 1 root root 253,   7 2022-12-24 21:41 productbrw------- 1 root root 253,   5 2022-12-24 21:41 system_extbrw------- 1 root root 253,   4 2022-12-24 21:41 system_rootbrw------- 1 root root 253,   6 2022-12-24 21:41 vendorblueline:/dev/bNpnxq/.magisk/block # cd ../mirror/blueline:####################################/dev/bNpnxq/.magisk/mirror # ls -altotal 24d---------  7 root   root    220 2022-12-24 21:41 .drwxr-xr-x  8 root   root    180 2022-12-24 21:41 ..drwxrwx--x 50 system system 4096 2022-12-24 21:41 datalrwxrwxrwx  1 root   root      9 2022-12-24 21:41 metadata -> /metadatalrwxrwxrwx  1 root   root     19 2022-12-24 21:41 persist -> /mnt/vendor/persistdrwxr-xr-x 14 root   root   4096 2009-01-01 08:00 productlrwxrwxrwx  1 root   root     17 1970-02-17 10:04 sepolicy.rules -> ./metadata/magisklrwxrwxrwx  1 root   root     20 2022-12-24 21:41 system -> ./system_root/systemdrwxr-xr-x  9 root   root   4096 2009-01-01 08:00 system_extdrwxr-xr-x 26 root   root   4096 2009-01-01 08:00 system_rootdrwxr-xr-x 20 root   shell  4096 2009-01-01 08:00 vendor

配置和模块(/data/adb目录)

不要被目录名迷惑,虽然是adb实际上是Magisk的一个应用目录,这个目录里面保存了Magisk的一些数据和配置文件,安装的模块也是被保存在这里,之所以使用这个目录是有它的优势的:

  • 该目录对于任何出厂设备来说都存在,第三方APP无法据此检测Magisk。
  • 该目录权限默认为700,所有者为root,因此第三方APP无法进入和读写。
  • 该目录的安全上下文secontext是u:object_r:adb_data_file:s0,很少有进程有该权限。
  • 该目录在Device Encrypted (DE) storage,因此当FBE (File-Based Encryption) 设备在Direct Boot mode时或者解锁屏后即可使用。

这个目录下包含以下文件(配合Magisk启动流程来看更容易理解):

SECURE_DIR=/data/adb# 存储一些 post-fs-data 后需要执行的脚本的文件夹$SECURE_DIR/post-fs-data.d# 存放通用 late_start 服务脚本的文件夹$SECURE_DIR/service.d# Magisk 模块目录$SECURE_DIR/modules# 待升级的 Magisk 模块# 因为模块文件在挂载时修改是不安全的# 通过 Magisk 应用程序安装的模块将存储在这里,并在下次重启时合并到 $SECURE_DIR/modules$SECURE_DIR/modules_update# 数据库存储应用设置和root授权日志MAGISKDB=$SECURE_DIR/magisk.db# 所有与 magisk 相关的二进制文件,包括 busybox、scripts和 magisk 二进制文件。 用于支持模块安装、addon.d、Magisk应用程序等。DATABIN=$SECURE_DIR/magisk

Magisk启动过程

Magisk启动分为以下几步:Pre-Init,post-fs-data,late_start,Resetprop,这几个启动流程我们可以对应上Android系统启动,下面我详细说明一下:

Pre-Init 阶段

使用 magiskinit替换init并执行:

  • 先挂载所需的分区。 在传统的 system-as-root 设备上,切换root到/system;在2SI 设备上(使用systemless), 将 init 文件重定向到 magiskinit 并执行(原理是我们在patch boot的时候会重定向原来的init步骤 ),以此来挂载所需的分区。
  • 在 init.rc注入magisk服务
  • 对于使用 monolithic (整体的)安全策略的设备,从 /sepolicy读取安全策略;对于其它设备,用FIFO劫持selinuxfs nodes,设置 LD_PRELOAD 来hook security_load_policy ,并且协助劫持2SI 设备,并且启动daemon直到init尝试读取sepolicy。
  • Patch sepolicy 规则。如果使用 “劫持” 方法, 则将修补的sepolicy载入kernel, 然后解除init 劫持并退出daemon。
  • 执行原始的 init 来执行后续的启动过程

post-fs-data阶段

post-fs-data 过程在 /data 解密并挂载后触发。首先会启动守护进程 magiskd ,执行post-fs-data脚本,这个时候模块文件就挂载完毕了。

late_start阶段

在启动过程的后期, late_start 类会被触发,开启Magisk “service” 模式。服务脚本会在这个模式下执行。

到这里Magisk就完全启动了,上面就是App了,他只是负责一些配置的修改和状态显示,以及调用前面启动的服务和程序来执行,大概就是这样的过程。

修改属性(Resetprop)

正常来说,只有init能修改系统属性,非root进程只能读取无法修改。在有root时可以通过由init提供的property_service发送请求(比如adb可以使用setprop命令)来实现修改,但是通过这种方式不能修改和删除只读属性(以ro.开头的属性,例如ro.build.product),除非修改系统源码

resetprop 通过提取和patch AOSP中和系统属性相关的源代码,从而允许直接修改属性区域(prop_area),不再需要通过property_service来修改系统属性(实际上这个功能和GitHub开源的mprop的原理类似)。不过也正是因为绕过了property_service,所以需要有下面的注意事项:

  • 触发事件的修复:由于绕过了property_service,所以当属性改变时,在*.rc脚本中注册的on property:foo=bar 动作事件不会被触发(在init语言中这个叫做属性触发器)。但Mgisk考虑到了这点,所以默认情况下 resetprop设置属性时会和setprop一样,它会触发事件(通过先删除属性再通过property_service来设置属性来实现)。如果不想触发动作事件,可以使用-n参数禁用。

  • 实现重启也保留修改:持久属性(以persist.开头的属性,例如persist.sys.usb.config)在 prop_area 和 /data/property都有存储。默认情况下,删除持久属性时不会把它从持久化存储中移除,也就是说下次重启时持久属性会被恢复; getprop在不会从持久化存储中读取持久属性。但是对于resetprop ,可以使用-p参数,这样删除时会同时将该属性从 prop_area 和 /data/property中移除,读取时也会同时从prop_area 和 持久化存储中读取。

SELinux 策略

Magisk通过patch原来的sepolicy来确保Magisk的操作可以安全地执行。新的magisk域权限很高, magiskd和所有root shell都会在该域中运行。magisk_file是一个新的文件类型,该文件类型允许每一个域访问(不受限制的文件上下文),下面这个magisk文件用的就是magisk_file上下文。

blueline:/data/adb # ls -Zltotal 52drwxr-xr-x 3 root root u:object_r:magisk_file:s0     3488 2022-12-24 21:41 magisk-rw------- 1 root root u:object_r:adb_data_file:s0  40960 2022-12-27 02:22 magisk.dbdrwxr-xr-x 2 root root u:object_r:system_file:s0     3488 2022-12-24 21:41 modulesdrwxr-xr-x 2 root root u:object_r:adb_data_file:s0   3488 2022-12-24 21:41 post-fs-data.ddrwxr-xr-x 2 root root u:object_r:adb_data_file:s0   3488 2022-12-24 21:41 service.d

在 Android 8.0之前,所有被su允许的客户端域都可以直接连接到 magiskd 并且与守护进程连接,从而获得远程的root shell访问。Magisk同时也需要释放一些ioctl 操作以便root shell可以正常工作。

但是,在Android 8.0及以后,为了避免Android沙箱中对规则的放松,Magisk实现了一个新的SELinux模型。 magisk二进制文件被标记为magisk_exec文件类型,进程在以su client的域运行时执行 magisk二进制文件(包括su命令)时会被中转为 magisk_client(通过使用一个type_transition规则)。

规则严格限制了magisk域的进程才被允许归属于magisk_exec文件类型。不再允许直接通过Socket连接至magiskd;唯一的访问该守护进程的方式就是通过一个magisk_client 进程。这样做确保了沙箱的完整性,让Magisk专用规则从其它规则中分离。如下magisk64:

blueline:/dev/bNpnxq # ls -lZtotal 720lrwxrwxrwx 1 root    root    u:object_r:system_file:s010 1970-02-17 10:04 magisk -> ./magisk64-rwxr-xr-x 1 root    root    u:object_r:system_file:s0                        154452 1970-02-17 10:04 magisk32-rwxr-xr-x 1 root    root    u:object_r:magisk_exec:s0                        247168 1970-02-17 10:04 magisk64-rwxr-xr-x 1 u0_a206 u0_a206 u:object_r:app_data_file:s0:c206,c256,c512,c768  328240 2022-12-24 21:41 magiskpolicylrwxrwxrwx 1 root    root    u:object_r:system_file:s0 8 1970-02-17 10:04 resetprop -> ./magisklrwxrwxrwx 1 root    root    u:object_r:system_file:s0 8 1970-02-17 10:04 su -> ./magisklrwxrwxrwx 1 root    root    u:object_r:system_file:s014 1970-02-17 10:04 supolicy -> ./magiskpolicy

关于更加详细规则可以在 magiskpolicy/rules.cpp中找到。

来源地址:https://blog.csdn.net/zhonglunshun/article/details/128791807

--结束END--

本文标题: Magisk内部实现原理

本文链接: https://www.lsjlt.com/news/386851.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Magisk内部实现原理
    Android10以后,Android系统限制了System分区的修改,结果就是,即使你i是自己编译的Android系统,即使是有做高的root权限,你依然无法挂载System分区并对其内容进行修改...
    99+
    2023-08-31
    android linux ubuntu
  • mysqldump内部实现原理的示例分析
    小编给大家分享一下mysqldump内部实现原理的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!我们可以通过打开gene...
    99+
    2024-04-02
  • Ajax的内部实现机制、原理与实践小结
    Ajax(Asynchronous JavaScript and XML)是一种在Web应用中实现异步数据交互的技术。它的内部实现机...
    99+
    2023-08-15
    Ajax
  • Go定时器内部的实现原理是什么
    这篇文章主要讲解了“Go定时器内部的实现原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go定时器内部的实现原理是什么”吧!前言本节,我们重点关注系...
    99+
    2024-04-02
  • 深入探索:Go WaitGroup的原理和内部实现
    WaitGroup是Go语言中的一个并发同步原语,用于等待一组goroutine的完成。它提供了三个主要的方法:Add、Done和W...
    99+
    2023-10-08
    Golang
  • Android中分析Jetpack Compose动画内部的实现原理
    目录前言正文总结前言 Compose的动画Api用起来很简单,效果看起来很神奇,那么它内部到底是如何运转的呢 使用动画的代码示例: var isOffset by remember ...
    99+
    2024-04-02
  • JavaScript内部原理是怎样的
    本篇文章给大家分享的是有关JavaScript内部原理是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。简介Javascript &nbs...
    99+
    2024-04-02
  • Java中的Kotlin 内部类原理
    目录Java 中的内部类OutterJava.classInnJava.classKotlin 中的内部类总结Java 中的内部类 这是一个 Java 内部类的简单实现: publi...
    99+
    2024-04-02
  • 夯实Java基础系列18:深入理解Java内部类及其实现原理
    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h3pl/Java-Tutorial喜欢的话麻烦点下Star哈文章首发于我的个人博客:www.how2pla...
    99+
    2023-06-02
  • MySQL排序的内部原理是什么
    MySQL排序的内部原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。排序,排序,排序 我们通过explain查看My...
    99+
    2024-04-02
  • 深入理解Golang方法的内部实现
    Golang是由Google开发的一种静态类型的编程语言,以其简洁的语法和高效的性能而备受程序员欢迎。在Golang中,方法是一种特殊的函数,用于为结构体添加行为。本文将深入探讨Gol...
    99+
    2024-02-23
    深入理解 内部实现 golang方法
  • linux内核锁的实现原理是什么
    Linux内核锁的实现原理是通过硬件的原子操作指令或者特殊的指令序列来保证对共享资源的原子操作,从而实现线程之间的同步和互斥。Lin...
    99+
    2023-10-21
    linux
  • Linq内部执行原理是怎么样的
    这篇文章主要介绍了Linq内部执行原理是怎么样的,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Linq内部执行原理LINQ(Language Integrated Query...
    99+
    2023-06-17
  • sga中library cache的内部原理是什么
    本篇文章给大家分享的是有关sga中library cache的内部原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 一、概述libr...
    99+
    2024-04-02
  • 揭秘 Java 文件操作的内部原理
    文件系统 API Java 文件操作的内部原理与操作系统的文件系统 API 密切相关。在 Java 中,文件操作是由 java.nio 包中的 java.nio.file 模块提供的。该模块提供了对文件系统 API 的封装,使 Ja...
    99+
    2024-02-26
    Java、文件操作、内部原理、读写、创建、删除
  • Session实现原理
    HTTP协议 ( http://www.w3.org/Protocols/ )是“一次性单向”协议。 服务端不能主动连接客户端,只能被动等待并答复客户端请求。客户端连接服务端,发出一个HTTP Request,服务端处理请求,并且返回一个H...
    99+
    2023-06-03
  • 如何进行ConcurrentHashMap内部实现
    如何进行ConcurrentHashMap内部实现,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。ConcurrentHashMap可以说是...
    99+
    2024-04-02
  • HashMap原理及手写实现部分区块链特征
    目录写在前面JDK7和JDK8中的HashMap正文写在前面 最近有很多的粉丝私信我,说自己在面试的时候,老是被人问HashMap的原理,但是在实际的工作中,也只是使用HashMap...
    99+
    2024-04-02
  • java中内部类出现内存泄漏的原因是什么
    这篇文章给大家介绍java中内部类出现内存泄漏的原因是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序...
    99+
    2023-06-14
  • 解析Flink内核原理与实现核心抽象
    目录一、环境对象1.1 执行环境StreamExecutionEnvironmentLocalStreamEnvironmentRemoteStreamEnvironmentStre...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作