type
status
date
slug
summary
tags
category
icon
password
URL
再和nano banana大战三百回合之后,我终于将刷机的基础知识用非常友好的方式展示出来,做出了一个我自认为可以扫盲的基础教学文档。在这个刷机越来越小众的时代,希望对这个小众圈子有些帮助。
免责声明
笔者是很多年前的刷机Root的脚本小子,但是并没有了解太多底层知识,主要是这么多年,安卓早就进行了非常大的变动,所有的一切都是AI辅助下的教程制作
Root到底意味着什么?
在很多年前,智能手机刚刚兴起的时候,手机性能孱弱,而且安卓并没有类似苹果的唯一应用安装入口来保证应用的质量,这就给了大量流氓软件肆虐的机会。当你安装一个软件,就会自动安装流氓全家桶(比如当初某某数字名称的浏览器,好像叫啥2345)。如果你有一个聪明的脑子,灵巧的双手以及无从打发的时间,学会Root,就能让你同时享受低价的安卓机,以及不输苹果的使用体验。
那么这么多年过去了,安卓手机的硬件厂商不断竞争,从处理器到屏幕,再到动辄上百瓦的快充,再到xxx亿的像素,以及各个手机都以及有了唯一的官方应用商店,应用生态早就今非昔比。当前Root的意义是什么?恕我浅薄,我觉得30%的人群可能是为了对抗云控,不让厂商在每年发布新手机的时候,为了让我们换机,搞这些下三路的手段;70%可能就是为了开挂游戏,破解程序啥的。嗯,人们对于白嫖的追求是刻进底层DNA的。
安卓启动的流程
我们知道,所谓Root,就是拿到两样东西
- root权限(su文件,sudo命令)
- Hook(钩子,偷梁换柱,将应用调用的函数偷偷改掉)
为了实现这个目的,需要先在安卓操作系统中植入一个su文件,并且只能由我们自己调用,还要想办法偷偷修改应用的进程来达到Hook目的。因此,我们先要了解安卓启动的全流程,看看哪一步可以悄悄地把su文件塞进去,还不被系统发现。
安卓系统的启动大概可以分为以下几步:
- Bootloader模式:最最最底层的模式,也叫Fastboot模式,常常用来线刷
- BootLoader会从ROM的特定扇区去读取boot.img数据流


- boot.img里面藏着kernel(内核)和Ramdisk(启动盘)
- bootloader会去启动kernel,kernel完成硬件的初始化


- kernel会去启动ramdisk(把ramdisk从boot.img解压到内存中,并临时挂载)

- ramdisk是一个临时的文件系统

- ramdisk开始干活,ramdisk中有一个init进程,是后续所有进程的唯一祖先,init通过阅读init.rc这个脚本,开始启动

- 如果你的手机按下了音量加+开关机键,那么bootloader会将这个暗号传递给ramdisk(启动引导),那么ramdisk就会去启动recovery分区(另一个小型操作系统,一般用来升级用的);
- 如果是正常启动的话,就是ramdisk会去启动system分区(我们看到的使用的安卓系统),下面的图中,显示的是已经被root的启动流程,偷偷地偷梁换柱把boot.img的ramdisk改了,不管改没改,发证ramdisk会去启动安卓system分区,进入我们看到的系统。




- 在我们看到的安卓system分区中,会有一个Zygote的进程(英文为受精卵,非常形象),我们后续手机中所有的应用进程(微信,QQ,支付宝)都诞生于Zygote

- 至此,从插电开机到启动应用程序(支付宝,微信)的整体流程就结束了,大致流程如下表。

总体来看,流程其实还挺长的,但是越是长的启动流程,留给我们偷梁换柱的空间机会就越大。手机厂商肯定不希望我们修改他们的系统(断人财路如杀人父母),因此system分区没法直接修改,那就不妨一层一层往前面找。最最外层是Bootloader,如果这一层可以修改,那就完美了,中间的启动链条的每一步都能偷偷修改,因此所有的Root都需要我们先去解开BL锁。
Magisk刷面具流程
当我们解开BL锁之后,可以对Boot.img就行随意替换还能正常启动,这就需要了magisk工具。magisk工具通过魔改Boot.img中的ramdisk分区(解包,修改,再打包),把里面的init启动进程做了偷偷的修改,塞入了su命令,再去启动system分区。这样,我们就有了root权限。
再当system的zygote这个最最最原始的进程启动中,magisk偷偷往里面注入一小段hook代码来”下毒“,之后所以从zygote启动的应用进程(微信,支付宝)都将会被”感染”,所有进程的函数调用都会被这段代码截获,截获了就可以偷偷修改了。
比如,某些app会通过函数调用去查找当前系统是否被root,简单一点,就是去查出有没有su文件,当这个函数调用被我们的hook代码截获之后,我们就告诉应用”不,你不想知道,这里面没有su文件,这里很安全“,这样应用就会被欺骗。
这里只是最简单的比喻,真正的欺骗和反欺骗是无穷无尽的对抗。
一点点额外的知识
我们之前提到了,所有的应用进程都是fork自最初的zygote(受精卵)进程,这一点是来自安卓的独特设计。在Ubuntu中,也有用户空间进程的祖先(systemd),所有进程都能追溯到systemd。但是不同的是,在Ubuntu中,进程fork是正常的分道扬镳,子进程是无法复用父进程的内存空间,这是全新的,想要复用的话,要用线程。
但是在安卓中,fork是可以复用zygote的信息,zygote启动的时候就已经把安卓中成百上千的系统组件预加载了,当其他应用进程(比如支付宝)调用系统组件,就能非常快地启动(比如相机?)
那么为什么本质也是Linux,但是安卓要这么设计?因为安卓的虚拟机太重了,如果每个应用启动都是类似Ubuntu的fork,那么就会都启动一个全新的虚拟机,把成百上千的系统组件都再加载一边,然后解析代码,造成的影响就是点击图标,会需要3~5s才能看到界面,而且内存会瞬间暴涨(因为App都在加载同一份重复的基础库),等到关闭APP后,这些基础库又会全部关闭。
那么不同进程复用同一个基础库,在读的时候没啥问题,但是写的时候会造成冲突,因此这里又用刀了Copy On Write(COW)技术,当我们写的时候,为了不造成冲突,就才开始复制,读的时候不复制。
总结
刷机有风险,Root需谨慎
数据不保存,半夜两行泪

- 作者:假维斯
- 链接:https://airouter.me/article/jojo-magisk-root
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

.webp?table=block&id=29d6498c-e5c2-81db-8e4b-e244bef7a08e&t=29d6498c-e5c2-81db-8e4b-e244bef7a08e)
.webp?table=block&id=29d6498c-e5c2-81c0-a99d-c7634656aeb1&t=29d6498c-e5c2-81c0-a99d-c7634656aeb1)
.webp?table=block&id=29d6498c-e5c2-8142-95cf-f25aa5bf7c3c&t=29d6498c-e5c2-8142-95cf-f25aa5bf7c3c)
.webp?table=block&id=29d6498c-e5c2-81a6-9769-d0a36aa56ae1&t=29d6498c-e5c2-81a6-9769-d0a36aa56ae1)
.webp?table=block&id=29d6498c-e5c2-81b9-9097-ca18dffbaf26&t=29d6498c-e5c2-81b9-9097-ca18dffbaf26)
.webp?table=block&id=29d6498c-e5c2-8179-a7cc-f3e9ba78174b&t=29d6498c-e5c2-8179-a7cc-f3e9ba78174b)

.webp?table=block&id=2a46498c-e5c2-803f-a528-d55d2aaf203b&t=2a46498c-e5c2-803f-a528-d55d2aaf203b)

