sailfish 上修改 android Q
需要
- android系统镜像:10.0.0 (QP1A.191005.007.A3, Dec 2019) - d455265945bb936a653730031af7d7a4aba70dc0c775024666a53491c9833b61
- simg2img: Android sparse image转Linux image;用来将system.img, vendor.img转为可挂载的image
- img2simg: Linux image转Android sparse image;将可挂载的image转为可刷写的image
- X-Ways Forensics: 以16进制编辑文件内容,并支持ext4文件系统格式挂载文件
- IDA Pro:反汇编支持
- ARM 架构参考手册:汇编指令支持
解压谷歌官方镜像压缩包后得到以下文件树
1 | pwd |
工作目录和其文件树
下文的操作如无特殊说明,均在sailfish/sailfish-qp1a.191005.007.a3-factory-d4552659/sailfish-qp1a.191005.007.a3/image-sailfish-qp1a.191005.007.a3
中进行
1 | pwd |
关闭avb
avb功能首先对分区进行每4kb字节的数据生成校验值,并将这些校验值合并到一起生成一个校验值数据块,校验值数据块的大小取决于分区大小并将这个数据块称作avb metadata,最后将avb metadata附加到image结尾,一同刷写进android设备。
android设备启动时,首先对avb metadata的root节点进行校验,如果通过则继续启动,否则将陷入bootloop.
如果不关闭avb功能,对分区的修改会导致android设备bootloop或者修改的内容无法生效(无法生效是通过FEC向前纠错来实现的)。
avb metadata头部的magic number可以控制avb是否生效。通过修改avb metadata magic number可以关闭avb功能;
校验元数据Magic number的定义如下:
#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // “VOFF”
在
android O
上可以直接修改boot.img/fstab.sailfish
文件,删除其中的verity
字段即可;这是因为boot.img中的root分区并没有被avb保护,所以可以直接修改root分区中的文件后重新打包root分区到boot.img中进行刷写。
在
android Q
上boot.img中的root分区被移动到system.img中,所以修改boot.img是不生效的。
关闭android Q的avb:
重命名
将
system.img
和vendor.img
分别命名为system.img.org
和vendor.img.org
以备份android sparse image转linux image
使用simg2img将
system.img.org
和vendor.img.org
分别转为system.img.raw
和vendor.img.raw
1
2simg2img system.img.org system.img.raw
simg2img vendor.img.org vendor.img.raw修改avb校验元数据Magic number
使用16进制编辑器
X-Ways Forensics
分别修改system.img.raw
和vendor.img.raw
中的校验元数据,将0xb001b001
修改为0x46464f56
;搜索16进制字符串
01B001B000000000
定位到校验元数据头Magic number的位置修改system.img.raw,偏移:
0x7EFE5000
修改vendor.img.raw,偏移:
0x1299b000
关闭selinux
android O
修改aosp源码init.cpp: selinux_is_enforcing函数,使该函数直接返回false。
重新编译init可执行文件。
boot.img解包后替换init可执行文件。
重新打包boot.img后刷写到android设备中。
android Q
boot.img中的根分区被移动到system.img中,init可执行文件也同样被移动到system.img中。
那么就需要对system.img中的init可执行文件进行修改,但是遇到一个问题就是system.img无法挂载为可读可写。并且remount时提示“写保护”。
1
2
3
4
5sudo mount system.img.raw system_raw
mount: /home/ccint3/Desktop/sailfish/sailfish-qp1a.191005.007.a3-factory-d4552659/sailfish-qp1a.191005.007.a3/image-sailfish-qp1a.191005.007.a3/system_raw: wrong fs type, bad option, bad superblock on /dev/loop6, missing codepage or helper program, or other error.
sudo mount -r system.img.raw system_raw
sudo mount -o rw,remount system_raw
mount: /home/ccint3/Desktop/sailfish/sailfish-qp1a.191005.007.a3-factory-d4552659/sailfish-qp1a.191005.007.a3/image-sailfish-qp1a.191005.007.a3/system_raw: cannot remount /dev/loop6 read-write, is write-protected.那么只能对system.img进行16进制编辑并保存,因此就需要
X-Ways Forensics
工具提供支持,这个工具支持以16进制编辑system.img,并且可以将system.img转为ext4的文件系统并编辑。阅读android Q的源码,了解如何关闭selinux
android Q上开启selinux的源码发生了变化,对selinux进行了独立的源码管理
查看IsEnforcing的调用关系,并定位到selinux.cpp: SelinuxInitialize
修改system.img中的init可执行文件
X-Ways Forensics
打开system.img,并将文件转换为磁盘将system.img磁盘中的
system/bin/init
可执行文件复制出来使用
IDA Pro x64
打开init可执行文件进行分析,因为从源码中我们知道SelinuxInitialize函数最终启动了selinux,因此我们在IDA中定位SelinuxInitialize函数,在SelinuxInitialize中有一些日志字符串,我们通过这些字符串就可以定位SelinuxInitialize的位置,例如:Loading SELinux policy
;在IDA中shift + F12
打开字符串窗口,并搜索Loading SELinux policy
获取以下结果对字符串参考引用后,最终定位到下图的位置
反汇编后,看到下图中的代码
关键代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13// 因为编译器内联汇编的原因,IsEnforcing函数直接被替换为了常量 1
// 与 security_getenforce 的返回值做比较
if ( (unsigned int)security_getenforce() != 1 )
{
// 因为编译器内联汇编的原因,所以security_setenforce函数的参数被替换为了常量1
// 通过 security_setenforce(1) 来启动selinux
// 因此我们需要修改security_setenforce函数的参数,将参数该为0,表示关闭selinux
v6 = (android::base *)security_setenforce(1LL);
if ( (_DWORD)v6 )
{
// ...
}
}我们的最终目的是修改
security_setenforce(1)
为security_setenforce(0)
即可关闭selinux;因为默认请情况下
security_getenforce
返回1,表示默认启动selinux;那么security_getenforce() != 1
则表示不会调用security_setenforce
函数。至此我们明确了需要修改的两处内容:
1:将
security_getenforce() != 1
修改为security_getenforce() != 0
2:将
security_setenforce(1LL)
修改为security_setenforce(0LL)
转至汇编代码,查看对应的汇编代码并修改,汇编代码如下图所示:
偏移
6A8FC
处的汇编CMP W0, #1
修改为CMP W0, #0
CMP W0, #0
的汇编指令:0x7100001F
偏移
6A904
处的汇编MOV W0, #1
修改为MOV W0, #0
MOV W0, #0
的汇编指令:0x52800000
修改后如图所示
将修改的内容写到init文件中,查看代码偏移
6A8FC
和6A904
对应的文件偏移6A8FC
和6A904
;使用
X-Ways Forensics
打开init文件,并跳转至文件偏移后,将汇编指令写入该位置:修改后:
关闭adbd指纹认证
android O
修改aosp adbd源码,重新编译之后,解包system.img,替换system.img中的adbd可执行文件,然后对system.img重新打包,之后刷写进android设备即可。
android Q
实现方式同
关闭selinux
类似,定位adbd源码位置,查看如何在源码级关闭指纹认证。之后使用IDA Pro
修改对应的汇编,最后在X-Ways Forensics
中修改system.img中adbd的文件内容。源码位置:adb/daemon/main.cpp:adbd_main
关键代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14int adbd_main(int server_port) {
// ...
// If ro.adb.secure is unset, default to no authentication required.
auth_required = android::base::GetBoolProperty("ro.adb.secure", false);
if (is_device_unlocked()) { // allows no authentication when the device is unlocked.
auth_required = android::base::GetBoolProperty("ro.adb.secure", false);
}
adbd_auth_init();
// ...
return 0;
}全局变量
auth_required
为true
时,开启adbd指纹认证,为false
时则关闭指纹认证。该变量通过
ro.adb.secure
来控制,在default.prop
中设置该属性,或者修改GetBoolProperty
函数的返回值。在system.img中复制出
system/bin/adbd
可执行文件,并使用IDA Pro x64
打开。
通过ro.adb.secure
字符串参考引用来定位adbd_main
函数的位置。最终定位到如下图所示:关键代码的反汇编如下:
查看对应的汇编代码如下:
偏移
20F0
处的汇编AND W8, W0, #1
修改为MOV W8, #0
MOV W8, #0
的汇编指令:0x52800008
修改如下:
最后通过
X-Ways Forensics
将修改的内容应用到system.imgsystem/bin/adbd
中
禁止adbd root权限降级
修改方式同关闭adbd指纹认证
源码位置:
adb/daemon/main.cpp:drop_privileges
adb/daemon/main.cpp:should_drop_privileges
关键代码如下:
1 | int adbd_main(int server_port) { |
读取ro.secure
和service.adb.root
属性并判断是否需要降级。
我们需要将should_drop_privileges
的返回值改为false
;通过字符串ro.secure
使用IDA Pro x64
定位到目标代码位置。并反汇编后代码如下:
需要修改的汇编位置如下:
偏移2270
处汇编 AND W8, W10, #1
修改为MOV W8, #0
偏移22C8
处汇编ORR W21, W9, W8
修改为MOV W21, #0
偏移22D0
处汇编AND W8, W8, #1
修改为MOV W8, #0
偏移22E8
处汇编AND W21, W21, W9
修改为MOV W21, #0
偏移245C
处汇编550400948000F8364B0400941F1800710D420054
修改为0xD503201F*5
开机启动adbd,无需打开开发者模式并勾选USB调试
android Q上通过修改vendor.img中的etc/init/init.usb.rc
来影响adbd的启动
将init.usb.rc
修改为:
1 | on property:sys.usb.config=mtp |
修改后的init.usb.rc
相比源文件有所缩短,为了不破坏文件,我们还需要维护这个文件在ext4文件系统inode块文件大小。通过X-Ways Forensics
跳转至该文件的inode
数据块,统计修改后这个文件的真实大小并修改inode
数据库记录即可。
最后保存修改并刷写至手机即可