之前写了类似的文章,但是这个文章办法不适用于小米10,
主要有几个问题:
1. supolicy这个在小米10 中root之后运行不起来,直接segment fault.
2. 小米的文件系统remont 成rw失败,提示
1|vangogh:/data/local # mount -o remount,rw /
'/dev/block/dm-4' is read-only
root
3. 即使修改了ro.secure 和 ro.adb.secure, 原版小米10的adbd启动后权限还是shell ...
解决办法如下, 大前提,你得先要把小米10 root了,可以使用su权限获到root的权限。
1. 下载android 10 的 aosp_arm64-img https://ci.android.com/builds/submitted/7064523/aosp_arm64-userdebug/latest,
2. 解压aosp_arm64-img-7064523.zip得到system.img文件, 用以下命令得到debug版的adbd
mkdir /mnt/system
mount -o ro system.img /mnt/system
#一定要-o ro 要不然默认是rw, mount不成功.
#复制得到debug版本adbd
cp /mnt/system/system/bin/adbd adbd
因为是ext2文件系统,使用linux比较方便,macos也可以使用fuse。可以用file命令来判断这个image是raw的img还是sparse的img, 要是sparse img, 还需要使用simg2img命令来转一下, 需要的话,使用brew , yum , apt之类的工具安装。
$ file system.img
system.img: Linux rev 1.0 ext2 filesystem data, UUID=4729639d-b5f2-5cc1-a120-9ac5f788683c (extents) (large files) (huge files)
3. 上传adbd到 手机
adb push adbd /mnt/sdcard
adb shell su -c mv /mnt/sdcard/adbd /data/local/
adb shell su -c chmod +x /data/local/adbd
4. 编写脚本adbdroot, system_properties_arm64是专门用于修改ro.开头的只读系统变量的,ro开头是只读,使用setprop是无法修改的,具体原理看https://bbs.pediy.com/thread-222293.htm
Upload system_properties_arm64 and adb to /data/local/
stop adbd
/data/local/system_properties_arm64 ro.secure 0
/data/local/system_properties_arm64 ro.adb.secure 0
cd /data/local/
nohup ./adbd >/dev/null &
5.上传adbdroot到手机,并执行
adb push adbdroot /mnt/sdcard/
adb shell su -c mv /mnt/sdcard/adbdroot /data/local
adb shell su -c chmod +x /data/local/adbdroot
adb shell su -c /data/local/adbdroot
6. 使用whoami测试, 得到adb shell权限默认就是root,不需要再su一下了,使用原来的脚本工具,调试就很方便了。
$ adb shell whoami
root
本文用到的资源我上传了一份在这里,adbd和system_properties_arm64 , , 方便大家直接使用。
附,关于root环境下直接修改ro属性, 上面有提到,是pediy的liwugang 发布的,此处,我觉得这个办法应该是众多办法中最好的一个,故转载内容在下面,以示敬意:
----------以下是转载内容---------------------
Android root环境下直接修改ro属性(只读properties)
属性是由init进程读取到内存中,然后通过mmap只读方式共享到其他进程中。读的时候每个进程都可以直接读取,而修改或者添加只能由init进程来进行,这样方便selinux权限管理。
有root权限后,我们可以将属性内存通过mmap读写的方式共享到我们的内存中,这样可以任意修改,绕过init的限制。
属性内存结构
* +-----+ children +----+ children +--------+
* | |-------------->| ro |-------------->| secure |
* +-----+ +----+ +--------+
* / \ / |
* left / \ right left / | prop +===========+
* v v v +-------->| ro.secure |
* +-----+ +-----+ +-----+ +-----------+
* | n | | sys | | com | | 1 |
* +-----+ +-----+ +-----+ +===========+
*
上图其实很形象,是字典树和二叉树的混合。结点信息数据结构如下:
typedef struct prop_bt {
uint8_t namelen; // 该结点名字长度
uint8_t reserved[3]; // 对齐的作用
uint32_t prop; // 指向prop_info,里面保存key和value信息
uint32_t left; // 左兄弟,长度小于或者长度相同而名字小于当前结点
uint32_t right; // 右兄弟,长度大于或者长度相同而名字大于当前结点
uint32_t children; // 子结点
char name[0];
} prop_bt;
typedef struct prop_info {
uint32_t serial;
char value[PROP_VALUE_MAX]; // PROP_VALUE_MAX = 92,所以说属性值最大长度为91,'\0'结尾
char name[0]; // 属性名字
} prop_info;
思路:
1. Android N上,首先读取读取/property_contexts文件,获取属性前缀和security context
(selinux定义的)的关系,由于每个security context对应一个文件,所以需要通过前缀来找到对应的文
件,6.0及以下所以属性都保存在/dev/__properties__文件中,可以不读取/property_contexts文件
2. 打开对应的文件,将属性以'.'分隔,将第一部分和头结点对比,若相同则第二部分和children对比,不同,
若小于则继续使用第一部分比较left结点,若大于则比较right结点。依次类推,若最后部分和结点N相等,则N的prop就是所要找到prop_info.