一、分区布局基础
1.分区介绍
不同厂商和平台的分区布局会不一致,但是以下几个分区在所有android设备中都有,如boot、system、data、recovery、cache。一般的,设备的NANAD flash memory遵从如下分区布局:
- boot_loader:存储手机的boot loader程序,该程序的作用是当手机boot的时候初始化硬件、booting android kernel、实现其他可选的boot模式,如download mode。
- splash: 存储splash图标,即开机过程中第一个显示的图片,一般是厂商、制造商的logo。有的设备中,这个图片保存在boot loader里,并不形成一个单独的splash分区。
- boot: 存储android boot image,包括Linux kernel image(zImage)、the root file system ram disk(initrd)
- recovery: 存储一个最小的android boot image,提供失效保护的功能和服务。
- system: 存储android system image(挂载为/system)。 该image包含了android framework、libraries、system binaries、预置应用
- userdata: data分区,/data。
- cache: 存储recovery log、OTA升级包的地方。
- radio: 存储基带image。
2.确认手机的分区布局
有以下几种方法,可以用于确认手机的分区:
方法1. 查看/proc/partitions中的分区信息
cat /proc/partitions
该命令无需root权限,即可执行。方法2.可以在/dev/block/platform中by-name文件夹中进一步查到与每个分区名链接的block。
不过这一般就需要root权限了。没有权限,会执行失败,提示permission denied。
方法3.mount或cat /proc/mounts
通过mount命令,或查看/proc/mounts文件的内容,可以得到部分分区信息,这不需要root权限的:
方法4.其他可能可行的方法
/etc/vold.fstab文件
recovery log(/cache/recovery/last_log)
kernel log(dmesg命令或者查看/proc/kmsg文件)
二、boot大体流程
按下开机键后,
首先运行boot loader,完成硬件的初始化,并提供进入recovery模式(加载recovery image)或者进入download 模式的选择
之后,加载boot分区中的android kernel和initrd(android 根文件系统)到RAM;加载结束后,会跳入kernel继续boot;在kernel中执行运行android系统所必须的任务,如初始化内存、I/O区域、内存保护、CPU调度、设备驱动等等,一系列必要的任务结束之后,mount root file system,并启动用户空间第一个进程init。
然后,启动用户空间组件。init进程是所有其他用户空间进程的父进程,该进程起初运行时,根文件系统是可读可写的呢。/init.rc文件保存这init进程的配置信息,用于初始化操作系统中的用户空间组件,比如,开启rild(telephony用)、mtpd(VPN用)、adbd(adb用),还开启zygote服务,用于创建Dalvik VM并开启第一个Java组件system server,之后启动其他组件如telephony Manager。
最后,系统boot结束后,发送ACTION_BOOT_COMPLETED广播事件给所有注册过接受这一广播事件的application。系统完全boot起来了。
TIPS: Download Mode是啥
download mode通过使用flashing进程允许用户更新设备的永久存储。fastboot是一种常见的flashing方法/协议。
要进入download模式,就是在boot过程中,按下相应的组合键,按什么样的组合键,依手机品牌型号而定,一般网上可查到。
USB连接手机的boot loader和PC后,可以通过设备支持的download协议使得手机和PC通信。这些协议可以完成一系列任务,如flash 手机的分区、重启手机、下载并执行其他kernel image等等。
fastboot相关知识可参考:http://blog.youkuaiyun.com/wlc520123/article/details/69951208
三、boot loader的加锁、解锁
一般的,手机的boot loader是加了锁的,防止用户从boot loader层面修改手机img。加锁通常是通过签名验证实现。
对于加了锁的boot loader,必须先解锁,才可以实现boot loader层面的刷机。解锁bootloader,是进入fastboot模式,并执行fastboot oem unlock命令。
Google nexus手机默认是加锁了的,不过也提供了官方的解锁方法。
解锁boot loader后,若手机被盗,黑客可以通过刷入自定义的boot image或flash 自定义的recovery image,之后就可以拿到手机中的所有信息了。所以,为了保护个人信息,在解锁bootloader的时候,会将手机恢复出厂设置。但是,值得指出的是,若手机恢复出厂设置之前是加了密的,恢复出厂设置后,一些信息还是能被恢复的。
TIPS:自定义revocery image
recovery模式是android的标准机制,它允许软件更新以替代整个预置在手机中的系统软件,而并不会擦出用户数据。
它通常使用手工下载的更新包或通过OTA方式获取的更新包。
recovery image存储在recovery分区,它包含了很少的Linux image,只提供简单的用户接口,这些用户接口只能通过硬件来操作。
进入revocery 模式的方法也分两种:
一种:组合键,不同厂商可能有不同
二种:adb reboot recovery命令
revocery模式最常用的功能应该是升级了。升级包是一个zip压缩包。升级包是签名了的,升级的时候,会验证签名的有效性。
自定义revocery image也是可以的,修改AOSP代码库中的android recovery相关源码,一般修改包括:
1.对全盘的备份和存储
2.允许未签名的升级包,或者,允许自定义密钥签名的升级包
3.可选mount 设备分区或SD卡
4.提供USB将大量存储数据到SD卡或/data分区
5.adb命令使用,adb root权限
6.提供busybox功能
常用的自定义recovery image是ClockworkMod recovery和TeamWin recovery project.
四、root 具有解锁 boot loader的手机
root的最重要环节就是在system分区上运行一个su二进制文件,并赋予其合适的权限。这使得在用户需要的时候,允许申请分配并使用特权。su二进制文件通常与superUser.apk或者superSU.apk一起,APK提供一个操作SU权限的一个界面,当其他应用申请su权限的时候,apk给出一个界面供用户选择是否同意授权。另外,apk还管理这种授权是一次性的还是永久性的。
在boot loader没加锁或者可解锁的手机上,root很简单。首先解锁boot loader,然后用户可以自定义设备的修改了,有好几种方法给手机加入合适权限的su,如:
1.刷入带su的system image,大体操作方法是:
解压ext4格式的system image,加入su二进制文件,重新打包它,之后刷到手机中。
mkdir systemdir
simg2img system.img system.raw
mount -t ext4 -o loop system.raw systemdir
cp su systemdir/xbin/su
chown 0:0 systemdir/xbin/su
chmod 6755 systemdir/xbin/su
make_ext4fs -s -l 512M -a system custom-system.img systemdir
umount systemdir
2.对于支持AOSP的设备,可以通过编译android源码,得到userdebug或者eng版本,这样的版本system中自带了su命令了。将编译好的system再刷到手机中。
以上两种必须刷system.img。
fastboot flash system custom-system.img
还有一种不需要刷image的。
3.boot自定义的recovery image。自定义的revocery image通过自定义升级包允许我们将su文件拷贝到system分区并设置合适的权限。大体思路:
准备:下载自定义的recovery image(适合手机的)、su升级包(SuperSU/SuperUser等都可以)
步骤1.将二者放到/sdcard中
步骤2.将手机进入fastboot模式
步骤3.命令行执行fastboot boot recovery.img(/sdcard中的img)
步骤4.在recovery模式中的菜单里,选择zip文件升级,并选择下载的包含su文件的zip文件。
4.android 4.1之后,允许sideload功能。该功能允许通过adb升级,升级包不需要提前拷贝到手机中。命令如下:
adb sideload su-package.zip
其中,su-package.zip是保护su的升级包,放在电脑里,而不是手机里。
在有的设备中,解锁boot loader后,可以boot没签名的代码,但不能fash没签名的代码。这种情况下,就需要先boot system,然后获取root权限,最后再flash 自定义的system/recovery image了。这样,需要使用dd将自定义的revocery image直接写到设备的recovery分区中。
五、root具有加锁boot loader的手机
当boot loader加锁了,而且厂商没有提供合法的解锁方法,我们就只能通过寻找设备的漏洞来root手机了。
首先要做的是,确定设备boot loader锁的类型。有以下可能的类型:
a.不允许进入fastboot模式,但通过尝试提供的flash 协议仍然可以成功flash
b.同一个设备,使用fastboot的时候,要求两次签名必须不一致。签名的验证可能发生在boot期间、flash期间,或二者兼具
c.有的加锁的boot loader仅对部分分区强制签名验证。典型地,若设备bootloader和recovery 分区加锁了,boot自定义的kernel或修改recovery image不可能了,但是我们仍然可以修改system 分区。见第四部分。
d.有的设备,boot分区加锁了,禁止boot自定义kernel,但是可以在recovery 分区flash自定义的boot image,并且通过recovery模式boot带有自定义kernel的系统。这样的话,通过在adb shell中修改default.prop文件可能可以root。
adbd进程起初是以root权限运行的,当boot image initrd执行了ro.security=1的时候,将其权限从root变为shell;另外,ro.kernel.qemu=1时,adbd进程也是root权限运行(该属性也是只读属性,实际设备上通常不可设置)。
android 4.2之前,boot的时候会读取/data/local.prop文件,并按其中内容设置系统属性,4.2之后该文件只在ro.debuggable=1的设备上才会读。
/data/local.prop文件、ro.secure和ro.kernel.qemu属性是root的关键。始终记住这点。好多漏洞就是利用这种思路来root手机的。
e.有的设备,可以使用android test key签名的recovery image包升级recovery image。这个test key在Google源代码中build/target/product/security目录中。我们可以通过自定义升级包(包含su文件)root手机。
f.最坏的情况,boot loader不允许我们boot任何签名验证失败的分区。就只能“软root”了,就是利用手机中没有打patch的漏洞来获取一个root权限运行的shell。通常,软root通过android kernel的漏洞、以root运行的进程、设置的set-uid位的漏洞程序、指向权限设置不当的文件的符号链接等等来获取root权限。设备中有很多可以利用的可能性,不光这些的。
TIPS:暂时root、永久root
当获取一个root shell之后,获取永久root就是下一步的目标了。
如果设备加了锁,则先需要将锁去掉。得到一个NANA unlocked的设备,此时,就可以以ro模式remount system分区了,再往里放su和对应apk,命令类似如下:
adb shell mount -o remount,rw /system
adb adb push su /system/xbin/su
adb shell chown 0.0 /system/xbin/su
adb shell chmod 06755 /system/xbin/su
adb shell mount -o remount,ro /system
adb install Superuser.apk
what is NAND LOCK:
A “NAND locked” (or “S-ON”) device is a device where the ROM (usually mounted at /system) is write-protected in hardware and thus cannot be modified, even if you have root privileges. Sometimes you get the illusion that you can write to /system, but in any case all changes will disappear after a reboot. This is why these devices often have “temp root” instead of “permanent root”. In order to get permanent root access, you need to make your device “NAND unlocked” (or “S-OFF”) first. In other words, you need to “unlock the bootloader”.
还有一种获取永久root的方法:
往recovery分区写入一个自定义recovery img。这需要dd命令。
先确认recovery分区对应的块:
shell@android:/ # ls -l /dev/block/platform/*/by-name/recovery
lrwxrwxrwx root root 2012-11-20 14:53 recovery -> /dev/block/mmcblk0p7
其次将自定义的image包放入sd卡,再写入recovery分区:
adb shell push custom-recovery.img /sdcard/
adb shell dd if=/sdcard/custom-recovery.img of=/dev/block/mmcblk0p7
最后重启设备,运行自定义的recovery(包含su)
adb reboot recovery
六、root举例
Kernel: Wunderbar/asroot(CVE-2009-2692)
Recovery: Volez
Udev: Exploid(CVE-2009-1185)
Adbd: RageAgainstTheCage
Zygote: Zimperlich and Zysploit
Ashmem: KillingInTheNameOf and psneuter(CVE-2011-1149)
Vold: GingerBreak(CVE-2011-1823)
PowerVR: levitator
Libsysutils: zergRush(CVE-2011-3874)
Kernel: mempodroid(CVE-2012-0056)
File Permission and Symbolic Link–Related Attacks
Adb Restore Race Condition
Exynos4: exynos-abuse
Diag: lit / diaggetroot(CVE-2012-4220)