首页
社区
课程
招聘
[原创]Magisk(v27) 源码分析 - 直接安装流程
发表于: 3天前 1992

[原创]Magisk(v27) 源码分析 - 直接安装流程

3天前
1992

直接安装流程:

通过界面分析,查看到直接安装相关代码,位于:

1
2
//相关代码位置:
app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt

直接安装执行以下代码:

1
protected fun direct() = findImage() && extractFiles() && patchBoot() && flashBoot()

findImage 执行流程:

1
2
3
4
//设置环境变量RECOVERYMODE=false, 执行util_functions.sh中的函数find_boot_image,输出$BOOTIMAGE
RECOVERYMODE=false find_boot_image; echo $BOOTIMAGE
 
//通过阅读 find_boot_image 中的代码,可知程序循环查找/dev/block 下的名为:ramdisk recovery_ramdisk kern-a android_boot kernel bootimg init_boot boot lnx boot_a的文件,将文件readlink,即可得到BOOTIMAGE对应设备。

extractFiles 执行流程:

1
2
//解压相关工具到内部文件目录
/data/user_de/0/com.topjohnwu.magisk/install/

patchBoot 执行流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//调用脚本 boot_patch.sh
cd /data/user_de/0/com.topjohnwu.magisk/install/
KEEPFORCEENCRYPT=false \
KEEPVERITY=false \
PATCHVBMETAFLAG=false \
RECOVERYMODE=false \
LEGACYSAR=false \
sh boot_patch.sh /sdcard/boot.img
 
//boot_patch.sh中 第一个操作是 解压boot.img。
//从函数unpack 分析得知,是从boot.img,分别获取:kernel、ramdisk.cpio、kernel_dtb、second、extra、recovery_dtbo、dtb 到当前目录中
magiskboot unpack /sdcard/boot.img
 
//boot_patch.sh中 第二个关键操作 是获取boot.img未修补之前的SHA1,如果未修补,通过
magiskboot sha1 /sdcard/boot.img
//计算得到Sha1.
//如果已修补,执行以下命令,还原得到SHA1.
//extract .backup/.magisk config.orig 如果存在.magisk 备份为config.orig
//restore 将boot.img中存在的.backup 删除
magiskboot cpio ramdisk.cpio "extract .backup/.magisk config.orig" "restore"
 
//boot_patch.sh 第三步,为ramdisk打补丁。
//将magisk32、magisk64、stub.apk 压缩为 xz格式
./magiskboot compress=xz name name.xz
//然后执行以下操作
./magiskboot cpio ramdisk.cpio \ 
"add 0750 $INIT magiskinit" \   //让magiskinit替换原版的init
"mkdir 0750 overlay.d"
"mkdir 0750 overlay.d/sbin"
"$SKIP32 add 0644 overlay.d/sbin/magisk32.xz magisk32.xz"
"$SKIP64 add 0644 overlay.d/sbin/magisk64.xz magisk64.xz"
"add 0644 overlay.d/sbin/stub.xz stub.xz"
//为了对抗dm-verify,如果环境变量中有KEEPVERITY和KEEPFORCEENCRYPT这两个标识,
//那么就移除fstab 中如下关键字:verifyatboot、verify、avb_keys、avb、support_scfs、fsverity
//forceencrypt、forcefdeorfbe、fileencryption
"patch"
"$SKIP_BACKUP backup ramdisk.cpio.orig"
"mkdir 000 .backup"
"add 000 .backup/.magisk config" //这里设置不可访问,里面存放的参数和原本boot.img的sha1
|| abort "! Unable to patch ramdisk"
 
//boot_patch.sh 第四步,对二进制文件进行补丁
//前两个针对三星手机处理,不做探讨
//最后一个命令,是将内核中 skip_initramfs 替换为 want_initramfs,将使cmdline中的skip_initramfs指令失效。
$LEGACYSAR && ./magiskboot hexpatch kernel \ 
736B69705F696E697472616D667300
77616E745F696E697472616D667300
&& PATCHEDKERNEL=true
 
//boot_patch.sh 第五步,根据第一步压缩出的文件,重新生成一个new_boot.img
./magiskboot repack "$BOOTIMAGE"

flashBoot 执行流程:

1
2
3
4
5
6
7
8
9
10
11
private fun flashBoot() = "direct_install $installDir $srcBoot".sh().isSuccess
    flash_image $1/new-boot.img $2
        local img_sz=$(stat -c '%s' "$1"//获取new_boot.img大小
        local blk_sz=$(blockdev --getsize64 "$2"//原有block大小,我这里是/dev/block/sdc29
        [ "$img_sz" -gt "$blk_sz" ] && return 1 //判断新镜像大于原有大小
        blockdev --setrw "$2"  //设置设备可读可写
        local blk_ro=$(blockdev --getro "$2"//查看设备状态是否为只读状态
        [ "$blk_ro" -eq 1 ] && return 2
        //执行刷机操作,将new-boot.img 内容+0 填充到/dev/block/sdc29中
        eval "cat /data/user_de/0/com.topjohnwu.magisk/install/new-boot.img" | cat - /dev/zero > /dev/block/sdc29 2>/dev/null
        

注:

1
2
3
4
//cpio格式文件解压命令
cpio -idmv<ramdisk.cpio
 
//magisk将自身所需文件压缩为xz格式,是因为xz格式压缩率最高

总结:

1、magisk 命令有很多可单独灵活应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//解包
magiskboot unpack boot.img
 
//对解压出来的ramdisk.img 做操作
magiskboot cpio ramdisk.cpio \
"extract src dest" \ //解压指定目标出来
"restore"  \ //对已经修补过的文件做恢复
"mkdir 0644 file" \ //新建目录
"add 0644 dest src" \ //添加或替换文件
 
//重新打包
magiskboot repack boot.img
 
//二进制文件修复
magiskboot hexpatch kerne searchhex patchhex

2、之前一直很纳闷magisk如何进行刷机,得到了解答,不需要借助别的工具,一句话搞定.

1
eval "cat /data/user_de/0/com.topjohnwu.magisk/install/new-boot.img" | cat - /dev/zero > /dev/block/sdc29 2>/dev/null

问题

实际上在多台机器上尝试,刷入boot.img是不生效的,github上的回应是因为运行时boot分区不可写入,所以这种直接刷入boot的方式是失效的。使用cat和dd得到了相同的内核错误,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
4,155484,5913747914,-;-(3)[7736:dd]print_req_error: 70 callbacks suppressed
3,155485,5913747916,-; (3)[7736:dd]print_req_error: critical target error, dev sdc, sector 1212416
4,155486,5913747925,-;-(3)[7736:dd]buffer_io_error: 10230 callbacks suppressed
3,155487,5913747929,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 0, lost async page write
3,155488,5913747947,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 1, lost async page write
3,155489,5913747954,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 2, lost async page write
3,155490,5913747961,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 3, lost async page write
3,155491,5913747967,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 4, lost async page write
3,155492,5913747974,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 5, lost async page write
3,155493,5913747980,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 6, lost async page write
3,155494,5913747987,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 7, lost async page write
3,155495,5913747993,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 8, lost async page write
3,155496,5913747999,-; (3)[7736:dd]Buffer I/O error on dev sdc29, logical block 9, lost async page write
6,155497,5913748695,-; (0)[0:swapper/0]sd 0:0:0:2: [sdc] tag#0 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x08
 SUBSYSTEM=scsi

疑惑点:github 作者的回应是否正确?有没有手段绕过这个限制? 请路过大神指点一、二


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (5)
雪    币: 707
活跃值: (1441)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

delta版本不是个功能 直接安装到system分区吗?

3天前
1
雪    币: 212
活跃值: (400)
能力值: ( LV3,RANK:38 )
在线值:
发帖
回帖
粉丝
3
hacker521 delta版本不是个功能 直接安装到system分区吗?
我之前一直没有注意到有这项,看了下条件:
四种安装方法显示需要的条件
```
选择并修补一个文件:没条件总是显示
直接安装(推荐):rooted
直接安装(直接修改/system): isRooted && !Info.isBootPatched  
安装到未使用的槽位(OTA 后): !isRooted || !Info.isAB || Info.isEmulator
```
需要满足root并且没有被magisk boot patch(主要是判断config里面SHA1项是否存在)

然后remount 为rw ,加入启动所有文件,替换bootanim.rc .

但这种方法可能只适用于模拟器,因为android10之后的动态分区是不能被remount,rw 的。

感谢提供思路
2天前
0
雪    币: 129
活跃值: (4485)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
capser 我之前一直没有注意到有这项,看了下条件: 四种安装方法显示需要的条件 ``` 选择并修补一个文件:没条件总是显示 直接安装(推荐):rooted 直接安装(直接修改/system): isR ...
android10 也是可以直接用的,前提是system可读写
2天前
0
雪    币: 707
活跃值: (1441)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
New对象处 android10 也是可以直接用的,前提是system可读写
是的 你mount过system分区即可
1天前
0
雪    币: 707
活跃值: (1441)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
capser 我之前一直没有注意到有这项,看了下条件: 四种安装方法显示需要的条件 ``` 选择并修补一个文件:没条件总是显示 直接安装(推荐):rooted 直接安装(直接修改/system): isR ...
需要你用额外的su文件去挂载magisk,这样magisk有root权限就可以安装到system分区,只有delta的magisk带这个功能,原版和alpha均不支持
1天前
0
游客
登录 | 注册 方可回帖
返回
//