Magisk内部实现原理

news2024/11/18 21:35:08

在这里插入图片描述

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 -al
total 720
drwx------  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 .magisk
lrwxrwxrwx  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 magiskpolicy
lrwxrwxrwx  1 root    root         8 1970-02-17 10:04 resetprop -> ./magisk
lrwxrwxrwx  1 root    root         8 1970-02-17 10:04 su -> ./magisk
lrwxrwxrwx  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 -al
total 0
d--------- 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 data
brw------- 1 root root 259,   4 1970-02-17 10:04 metadata
brw------- 1 root root 253,   7 2022-12-24 21:41 product
brw------- 1 root root 253,   5 2022-12-24 21:41 system_ext
brw------- 1 root root 253,   4 2022-12-24 21:41 system_root
brw------- 1 root root 253,   6 2022-12-24 21:41 vendor
blueline:/dev/bNpnxq/.magisk/block # cd ../mirror/
blueline:
####################################
/dev/bNpnxq/.magisk/mirror # ls -al
total 24
d---------  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 data
lrwxrwxrwx  1 root   root      9 2022-12-24 21:41 metadata -> /metadata
lrwxrwxrwx  1 root   root     19 2022-12-24 21:41 persist -> /mnt/vendor/persist
drwxr-xr-x 14 root   root   4096 2009-01-01 08:00 product
lrwxrwxrwx  1 root   root     17 1970-02-17 10:04 sepolicy.rules -> ./metadata/magisk
lrwxrwxrwx  1 root   root     20 2022-12-24 21:41 system -> ./system_root/system
drwxr-xr-x  9 root   root   4096 2009-01-01 08:00 system_ext
drwxr-xr-x 26 root   root   4096 2009-01-01 08:00 system_root
drwxr-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 -Zl
total 52
drwxr-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.db
drwxr-xr-x 2 root root u:object_r:system_file:s0     3488 2022-12-24 21:41 modules
drwxr-xr-x 2 root root u:object_r:adb_data_file:s0   3488 2022-12-24 21:41 post-fs-data.d
drwxr-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 -lZ
total 720
lrwxrwxrwx 1 root    root    u:object_r:system_file:s0                            10 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 magiskpolicy
lrwxrwxrwx 1 root    root    u:object_r:system_file:s0                             8 1970-02-17 10:04 resetprop -> ./magisk
lrwxrwxrwx 1 root    root    u:object_r:system_file:s0                             8 1970-02-17 10:04 su -> ./magisk
lrwxrwxrwx 1 root    root    u:object_r:system_file:s0                            14 1970-02-17 10:04 supolicy -> ./magiskpolicy

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/185687.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot+Vue项目企业客户管理系统

文末获取源码 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏…

Linux(centos7)基本操作---文件管理和用户管理

文件管理 文件的目录结构 文件的目录结构从根(/)目录开始,主要由一下几个目录组成,之间的作用也是不同的,具体作用如下: bin目录:主要存放系统中的一些基本的有执行权限(x&#…

动态AOP 自动以标签 源码解析

Spring AOP 是一个简化版的AOP 实现,并没有提供完整的AOP功能,通常情况下,Spring AOP 是能够满足我们日常开发过程中的大多数场景的,但在某些情况下, 我们可能需要使用Spring AOP 范围外的某些AOP 功能。 AspectJ是一…

【JAVA程序设计】(C00101)基于Servlet的在线鞋店销售管理系统

基于Servlet的在线鞋店销售管理系统项目简介项目获取开发环境项目技术运行截图项目简介 本项目是基于J2EE的servlet的在线鞋店销售管理系统,网上鞋店,球鞋,篮球鞋,跑步鞋,本项目有三种权限:游客、用户、管…

LeetCode 1480. 一维数组的动态和

有人相爱 有人深夜看海 有人LeetCode第一题都做不出来 小趴菜就是我 女神镇楼压压惊 文章目录LeetCode 1480. 一维数组的动态和题目描述:示例1:示例2:示例3:提示:解题思路题解结果展示大神题解执行消耗内存为 0 kb&am…

轻量级 K8S 环境、本地 K8S 环境Minikube,一键使用 (史上最全)

文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新 史上最全 面试必备 2000页 面试必备 大厂必备 涨薪必备 免费赠送 经典…

基于android的教育机构家校通系统app

需求信息: 客户端老师 1:用户注册与登录 2:添加作业信息;作业包含选择、填空以及简单题 3:查看自己添加的试题信息; 4:对学生提交的作业信息进行查看和批改; 5:和学生进行…

自学Vue开发Dapp去中心化钱包(三)

前言本篇主要记录学习Vue并实际参与完结web3门户项目的经验和走过的弯路。拖了这么久才来还债,说项目忙那是借口,还是因为个人懒!从自学到实战Vue实际中间就1周的学习熟悉时间,学习不够深就会造成基础不稳,多次推翻重来…

新的一年里技术管理者(工作者)们如何做好技术规划?

技术管理者的主要工作 技术管理者的主要工作是带人、做事、看方向: 带人是指团队人员能力的培养、团队梯队的建设等等;做事是指完成各项业务需求;看方向是指明确团队未来的发展方向和目标。我们经常会辩论“做管理了还要不要写代码”这个话题,而“写代码”只是“做事”里面…

Java——Maven项目管理

目录Maven1,Maven1.1 Maven简介1.1.1 Maven模型1.1.2 仓库1.3 Maven基本使用1.3.1 Maven 常用命令1.3.2 Maven 生命周期1.4.2 Maven 坐标详解1.4.3 IDEA 创建 Maven项目1.4.4 IDEA 导入 Maven项目1.5 依赖管理1.5.1 使用坐标引入jar包1.5.2 依赖范围Maven 目标 能够…

服务器与客户端的一般套路

WinSocket 套接字 ————服务器与客户端的一般套路 一、开发环境 IDE: Red Panda Dev-C 6.5编程语言:C语言库:winsock2.h 二、套接字工作流程图 注意:这个工作流程图非常重要,后面的代码编写基本就是这个逻辑 三、服务器各…

前端基于DOM或者Canvas实现页面水印

🐱 个人主页:不叫猫先生 🙋‍♂️ 作者简介:前端领域新星创作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫系列专栏:vue3从入门…

AtCoder Beginner Contest 287(A~E)

比赛名称:UNIQUE VISION Programming Contest 2023 New Year (AtCoder Beginner Contest 287) 比赛链接:AtCoder Beginner Contest 287 目录 A - Majority B - Postal Card C - Path Graph? D - Match or Not E - Karuta A - Majority 问字…

工作和学习中都能用到的5款实用软件

如今,工作和学习都离不开电脑,所以电脑里的软件自然也是必不可少的,但是电脑软件那么多,不可能每个都装上吧,所以我们要装好用的、实用的,下面给大家分享5款好用到爆的软件,很多懂电脑的人都在用…

【算法】雪花算法

一.特点 1.全局唯一性:对于大数据量的分库分表场景,例如水平分表需要保证主键id的全局唯一性。 2.趋势递增:整体的id趋势是递增的,不是单调递增。 3.不规则性:id不连续,无规则,不规则。 4.包含…

乾元通多卡聚合通信设备保障生态环境监测网络

针对目前城市大气环境监测网格化建设,推出的新一代城市网格化大气环境监测系统,可以实现城市区域环境多维一体化监测管理,该设备主要用于监测大气环境中的PM10、TSP、PM2.5等颗粒物浓度,还可以实现环境监控,测噪音、大…

Node.JS 安装配置 | 安装排错解析

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Node.js下载 Node.js官方下载地址 官方下载如果慢,请用如下地址下载: Node.js 中文网 根据自己计算机配置下载 Next Next 安装地址可更换 Next…

年后找工作必看的自动化测试面试宝典,一般人我不告诉他

目录 前言 1.1 什么是 API? 1.2 什么是 API 测试? 1.3 常见的 API 测试类型有哪些? 1.4 列举 API 测试中使用的一些常用协议? 1.9API 常见测试有哪些? 1.10API 测试有哪些优势? 1.11API 测试中究竟…

【PHP 随记】—— Composer 安装项目以及项目的扩展

👉总目录👈\large\colorbox{skyblue}{👉总目录👈}👉总目录👈​ 文章目录1、Composer 安装项目① 项目安装示例② 相关问题解决③ 框架搜索指南2、Composer 安装项目的扩展使用 Composer 更轻松方便地安装 P…

RV1126笔记二十五:区域入侵检测

若该文为原创文章,转载请注明原文出处。 一、 前言 区域入侵检测是通过识别目标之后获取目标坐标位置,判断目标是否在所标定的区域内出现,常常被用在电子围栏,不安全区域入侵检测,智慧城市,安防监控等领域。具体使用场景有,在标定的区域内不能抽烟,进入工地区域必须佩…