ROOT工具自带的su,
通常带有权限管理工具配套使用,
卸载了权限管理工具,su就无法使用,
是不是觉得很烦人呢?
别着急!
本期“安仔课堂”,
ISEC实验室刘老师手把手教你:
如何在Android 4.4以上版本DIY提权程序?
Android的提权程序实际上是手机系统分区中的一个su可执行程序。Android系统是基于linux内核,su相当于Linux
下
获取
ROOT
权限的命令,执行su命令后,当前用户会被切换成
ROOT
用户。
ROOT
用户是一种存在于UNIX系统和类UNIX系统(如Linux)中的唯一的超级用户,具有最高的系统权限。但是,手机厂商为了保证系统的安全性和完整性,手机出厂时是没有
ROOT
的,普通用户无法通过常规手段获取
ROOT
权限。
获取
ROOT
权限,常用的方法是把su程序写入到system分区,并赋予系统最高权限,后续手机上的程序调用su执行指定的命令获取到
ROOT
权限。
我们把获取手机
ROOT
权限的过程称为
ROOT
手机。
通常,ROOT手机的方法有以下三种,原理都是把系统改成可修改的状态,并把su写入system分区并赋予最高权限。
通常,
ROOT
手机的方法有以下三种
,原理都是把系统改成可修改的状态,并把su写入system分区并赋予最高权限。
一些公司发布的用于
ROOT
手机的
工具,如kingroot、一键
ROOT
等,这些工具利用系统漏洞(内核漏洞或者以
ROOT
权限运行的进程漏洞),将自身进程权限提升到
ROOT
权限,修改系统system分区,写入自己的su程序,达到
ROOT
手机的目的。
获取第三方修改后的
ROM
,这类
ROM
通常会把super su相关组件打包到镜像中,刷入系统后,会默认带有
ROOT
功能,不过这类第三方ROM的安全性没法保证,你无法确定作者是否加入了其他程序。
Recovery是Android手机恢复模式,在这种模式下,可以对手机进行升级、恢复出厂设置、清除数据等操作。通常,手机默认的recovery只有简单功能,比如升级、清除数据等操作。为了能够修改系统,可以刷入第三方recovery(如TWRP recovery),通过第三方recovery提供的功能,把super su刷入到系统中,达到
ROOT
目的。
su是elf格式,
Linux
下的可执行文件,之所以叫su,有切换用户(switch user)的意思,也可以改成其他名称。
在
Android
4.4以前,因为没有SEAndroid的限制,su的工作逻辑非常简单,把su程序的用户和用户组设置为
ROOT
并设置s位(set uid,set gid)。s位的作用是,如果其他用户执行该文件,该进程的euid会切换到0(
ROOT
),eguid·会切换到0(
ROOT
),因此就具有了
ROOT
用户的权限。
图 1、Android4.4以前的su二进制文件属性
图 2、Android下su的源码片段
在
Android
4.4
之后,SEAndroid默认开启,su的工作逻辑要比
Android
4.4以前的复杂。
原因有以下三点:
a、
ROOT
权限的概念已经模糊,就算进程具有
ROOT
权限(euid=eguid=0),也无法进行高权限操作。
b、
于权限的控制,是通过安全上下文(Security Context)和安全策略(Security Policy)控制。
可以通过ps -Z来查看一个进程的安全上下文:
图 3、ps查看进程的context
可以通过ls -Zl来查看一个文件的安全上下文:
图 4、ls –lZ 查看文件的context
在
Android
selinux中,对于进程,上下文为u:r:type:s0,其中,u、r、s0是固定的;文件上下文为u:object_r:type:s0 ,其中u、object_r、s0是固定的。一个进程能否对一个文件进行某种操作,是由进程中的type和文件的type决定的。
图 5、安全策略的部分
图5中,表示允许类型shell的进程,对类型的shell_data_file的文件(目录)进行,创建文件,创建目录。
c、
SEAndroid开启情况下,init进程的context为u:r:init:s0,是用户模式下拥有最高权限context,虽是最高权限,但也有很多限制(比如:init对android service和shell_data_file的某些操作是不被允许的),没有达到真正意义上的
Root
权限。
图 6、init.te策略文件中对init的限制
由于以上原因,
在SEAndroid存在的情况下,我们如何实现su提权呢?
通常采用如下所述的C/S架构模式,
在服务端动态修改SEAndroid的策略配置,来达到提权的效果。
由于SEAndroid的限制,在开启SEAndroid的系统上,su的实现通常使用C/S模式。系统启动时,通过init进程启动su的daemon进程,作为服务端,此daemon进程拥有u:r:init:s0的context,服务端启动后,通过从"/sys/fs/selinux/policy"或"/sepolicy"中读取security policy内容,修改后写入"/sys/fs/selinux/load";创建localsocket,等待客户端的连接。
客户端启动su后,通过localsocket,把pty设备信息发送给服务端,服务端通过打开访问对应的pty设备和客户端通信。客户端通过终端写入命令,发送到服务端执行,执行后返回结果。
图 7、客户端流程
图 8、服务端流程
C/S架构的su,服务端必须以用户模式下最高权限启动(即u:r:init:s0),通常做法是修改系统文件,随系统启动时由init进程启动。
a、
修改系统/system/etc/install-recovery.sh文件,install-recovery.sh是bash脚本文,由init进程启动,可以加入su服务端启动命令。如果在init.rc中对install-recovery进程设置了新的context u:r:install_recovery:s0,这种情况下就无法达到要求。
b、
替换系统文件,比如替换/system/bin/debuggerd文件,先备份原/system/bin/debuggerd为debuggerd_real,在新的debuggerd中先启动su的服务端,再启动原debuggerd_real.
c、
获取ROM包,修改ramdisk中的init.rc,加入启动su服务端的代码。
在明白了SEAndroid下su的原理后,就可以DIY自己的su
。
本文介绍的方法适用于可以自定义手机程序、不需要授权操作的使用场景,
比如:可以实现一个没有UI交互授权管理的su,放到手机系统分区指定的目录下,然后自定义授予我们想要的权限,
如我们自己的APP在请求
ROOT
权限时直接允许,其它则拒绝。赶紧动手试试吧!