Magisk简述
概述
Magisk 是目前最流行的安卓手机 root 解决方案。
虽然像小米等手机厂商也提供了所谓支持 root 的开发版 Rom,但在较新的版本中,他们无法直接写入像 /system/
之类的被保护的路径。这就导致了很多事情仍然做不了。最经典的就是连系统证书都修改不了。。。
而 Magisk 能避免写入被保护的路径,将自己的文件系统 “Mask” 在原生的文件系统上。这样既不需要直接修改的原始的数据,也能骗过程序使用 Magisk 提供的文件系统。
令人感叹的是 Magisk 的作者 topJohnWu 在发布项目的时候只是一名大二的学生,目前就职于 Apple 做机器翻译。
模块仓库
Magisk之所以火,很大程度上还是由于大家可以贡献自己的创造力分享自己写的Magisk模块。但是在使用别人的模块时还是要小心再小心。
官方的仓库其实只有 https://github.com/Magisk-Modules-Repo 这个由 JohnWu 自己维护的。这里的模块基本都可以放心使用。当然市面上也有各种其他的 Magisk 仓库,但是用这些的时候还是要先认真读一下代码吧。。。
Magisk安装
刷 TWRP
TWRP相关的信息可以在官网和一个非官方社区中搜索对应机型,并按照说明进行刷机。
当然,很大概率,这两个国外网站的信息可能不太适合社会主义国情,如果刷机失败了也不要灰心。国内的 @wzsx150 所在的 L.R.Team 在官方的基础上做了改进和懒人包教程并支持了Android10,也提供了国内大多数机型的刷机工具和教程,你值得拥有。
目前他们提供的相关内容在这里:
- 恒创互联云盘 网页链接 (密码:wzsx150)
最后需要注意的是,如果在刷入TWRP完成后手机重启前,没有通过 TWRP 安装一些如第三方rom(如Magisk或SuperSU),那么手机重启后,TWRP就会被原生recovery重新覆盖。。。
刷入 Magisk
在刷入 TWRP 进入新的 recovery后,就可以刷入 Magisk了。安装 Magisk 的步骤可以参考官方文档。
关于Root权限
通过 Magisk 可以获得有 root 权限的 shell,但是这个 root 权限依然是受限的。
获取 Root 权限
和原生的开发版不同,刷入 Magisk 的设备无法使用 adb root
这样的命令:
$ adb rootadbd cannot run as root in production builds
但是可以在进入 shell 后登入root 用户:
代码语言:javascript复制$ adb shell
cereus:/ $ su
cereus:/ #
当然,这需要在 Magisk 弹出的窗口中点击授权:
如果不想用交互式指令,则可以用 -c 参数:
代码语言:javascript复制$ adb shell su -c 'ls /data/data/'
android
android.ext.services
android.ext.shared
...
或者用管道实现:
代码语言:javascript复制$ echo 'ls /data/data/'|adb shell su
android
android.aosp.overlay
android.ext.services
android.ext.shared
...
不足之处
看起来我们可以在shell中直接获得root权限,但是当你修改了 /system 等目录下的文件后,你的所有变更在下次重启之后都会丢失。
因此这个 root 权限其实更像是一个 readonly 的root,并不是一个通用的 root。这个当然也并不是一无是处,在查看一些系统文件的时候还是很有帮助的。
持久化的 Root
要想获得真正的、能持久化的写文件的 Root 权限,就必须要通过自己编写 Magisk 模块,在启动的时候准备好需要覆盖的文件,像 Mask 一样加载进系统。
Magisk模块编写
基础知识
编写标准的 Magisk 模块建议直接参考 官方文档,这里不再赘述。需要注意的是 Magisk 模块的结构有过一次调整,因此存在新老两种模块的文件结构。当然新版的Magisk对这两种写法都做了兼容,但还是建议用新的写法。
如果需要学习自定义模块的写法,建议参考下面两个模块:
- v2ray 模块,用的是新模块写法,用于启动一个系统维度的 v2ray 服务(用于访问国外网站)。
- movecert 模块,用的是老模块的写法,用于将用户证书移动到系统证书的路径下,使系统默认信任用户证书。
另外还有几个注意点(新版写法):
customize.sh
中主要用于编写安装时执行的脚本,这里的脚本能够执行adb shell 中的指令。需要注意的是这个脚本只在安装过程中执行,重启后不会再次执行。- 启动后台服务的地方放在
post-fs-data.sh
或者service.sh
中;区别在于系统会阻塞等待post-fs-data.sh
执行完,而service.sh
则会与系统并发执行(常用于启动一些服务)。比较坑的是,这两个脚本使用的上下文是 magisk 自带的 busybox,因此在执行 adb shell 中的一些指令时,一定要使用绝对路径。 post-fs-data.sh
和service.sh
在每次系统重启后都会执行。- 修改 ro 开头的配置放在
system.prop
中,其他配置可以直接用setprop
命令。 - 注意给文件正确的权限。
红米6的实践
开启adb安全模式
小米开启adb安全模式默认需要登录小米账号,我们可以在 customize.sh
中修改配置绕过。
remote_provider_preferences=/data/data/com.miui.securitycenter/shared_prefs/remote_provider_preferences.xml
grep -q 'security_adb_install_enable' $remote_provider_preferences
if [ $? -ne 0 ] ;then
sed -i 's/</map>/<boolean name="security_adb_install_enable" value="true" />n</map>/g' $remote_provider_preferences
ui_print "- Insert security_adb_install_enable to true"
else
sed -i '/security_adb_install_enable/ s|([vV]alue=")[^"]*(")|1true2|g' $remote_provider_preferences
ui_print "- Change security_adb_install_enable to true"
fi
取消USB安装的确认框
小米在开启MIUI优化后,通过USB安装app会有个确认框,我们可以在 customize.sh
中修改配置绕过。
remote_provider_preferences=/data/data/com.miui.securitycenter/shared_prefs/remote_provider_preferences.xml
grep -q 'permcenter_install_intercept_enabled' $remote_provider_preferences
if [ $? -ne 0 ] ;then
sed -i 's/</map>/<boolean name="permcenter_install_intercept_enabled" value="false" />n</map>/g' $remote_provider_preferences
ui_print "- Insert permcenter_install_intercept_enabled to false"
else
sed -i '/permcenter_install_intercept_enabled/ s|([vV]alue=")[^"]*(")|1false2|g' $remote_provider_preferences
ui_print "- Change permcenter_install_intercept_enabled to false"
fi
一些页面优化
代码语言:javascript复制# 取消相关动画
settings put global window_animation_scale 0.0
ui_print "- Change window_animation_scale to 0"
settings put global transition_animation_scale 0.0
ui_print "- Change transition_animation_scale to 0"
settings put global animator_duration_scale 0.0
ui_print "- Change animator_duration_scale to 0"
# 保持开机状态
settings put global stay_on_while_plugged_in 7
ui_print "- Change stay_on_while_plugged_in to 7"
# 屏幕方向锁定
settings put system accelerometer_rotation 0
ui_print "- Change accelerometer_rotation to 0"
settings put system user_rotation 0
ui_print "- Change user_rotation to 0"
# ADB 配置
setprop persist.security.adbinput 1
ui_print "- Change persist.security.adbinput to 1"
setprop persist.security.adbinstall 1
ui_print "- Change persist.security.adbinstall to 1"
如果有一些其他配置需要统一修改,建议将手机的语言调成英文,然后在安卓源码或者 getprop
settings
命令中搜索相关的关键字。
关闭错误弹窗
由于未知原因,红米6 在刷入 Magisk 后必然会出现一个 "您的设备内部出现了问题。请联系您的设备制造商了解详情。" 的错误弹窗:
因此我们可以在 service.sh
中写一个自动关闭脚本:
dump_path=/data/local/tmp/dump.xml
for i in $(seq 1 10)
do
rm -f $dump_path
uiautomator dump $dump_path
grep -q '设备内部' $dump_path
if [ $? -eq 0 ];then
sleep 1
input tap 540 1270
rm -f $dump_path
sleep 1
uiautomator dump $dump_path
grep -q '设备内部' $dump_path
if [ $? -ne 0 ];then
echo "process done in $i times" >> $dump_path
break
fi
fi
sleep 10
done
自动设置PTP
又由于一些未知原因,手机在重启后总是默认充电模式,导致无法自动连接 adb 。经实践发现把连接模式强制设置为 PTP 模式可以解决,因此我们也可以在 service.sh
中加入如下自动设置脚本:
adb_log_path=/data/local/tmp/adb.log
for i in $(seq 1 10)
do
rm -f $adb_log_path
/system/bin/svc usb setFunction ptp true && /system/bin/svc usb getFunction &> $adb_log_path
sleep 5
done
考虑到启动加载顺序未知等原因,为了保险起见这里需要多循环执行几次,否则还是会有概率修改失败。。。
刷砖急救
常在河边走哪能不湿鞋。理论上只要一直搞机下去,迟早有一天会把手机刷成砖。刷成砖不可怕,可怕的是刷成的砖连 recovery、fastboot 都进不去、连 adb 都连不上。如果是这样,那基本就是真砖了。
目前我遇到了两种刷假砖后急救的case。
刷TWRP后无限重启
对于 红米9 等机型,直接刷入 recovery 后可能会一直无限重启。这时候只需要下载 vbmet.img ( tar -xvf vbmeta.tar ) 并在 fastboot 模式下把这个也刷进去即可:
代码语言:javascript复制$ fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img
装了第三方Magisk模块后无限重启
乱装 Magisk 模块改配置是有概率导致手机无法正常开机的。但是只要还能进 recovery ,那八成还是有救的。Magisk 的模块默认是安装在 /data/adb/modules/
下的,只要在 recovery 下找到有问题的模块文件夹并删除重启,多半都是能救回来的。具体可以参考 How to Uninstall Magisk Modules Using TWRP Recovery。
参考资料
Developer Guides | Magisk
每个 Android 玩家都不可错过的神器
How to Uninstall Magisk Modules Using TWRP Recovery
Install User Certificate Via ADB
Enable "Install via USB" without signing in to Xiaomi account