之前在搞Xposed的时候遇到一个问题是Xposed的卸载原本需要root权限,但是Xposed的原理是hack了zygote这个进程(xposed原理以后有时间再写),而zygote本身是有root权限的,所以Xposed应该是可以利用zygote的root权限来卸载自身。但是实际操作中发现并不可以。经过一番研究发现这是由于SEAndroid的缘故,zygote的一些操作会被SEAndroid限制,它的root权限并不是为所欲为的。下面就要详细的谈一下SEAndroid这个东西,然后再谈一谈如何去更改这个规则。
本文章有三个目的:
1.理解SEAndorid的工作原理
2.能够看懂SEAndroid的规则
3.能够自己增添删改其规则(这一条估计大多数人都用不到,所以前两条是主要目的)
1. SEAndroid 概念
SEAndroid 是SELinux 在Android 上面的一个移植。SELinux 是Linux上系统保护机制,SELinux 全称 Security Enhanced Linux (安全强化 Linux),是MAC (Mandatory Access Control,强制访问控制系统)的一个实现。其目的在于明确的指明某个进程可以访问哪些资源(文件、网络端口等)。Android系统基于Linux实现。针对传统Linux系统,NSA开发了一套安全机制SELinux,用来加强安全性。然而,由于Android系 统有着独特的用户空间运行时,因此SELinux不能完全适用于Android系统。为此,NSA同Google一起针对Android系统,在SELinux基础上开发了 SEAndroid。
Android 4.4首次引入了这一机制,SEAndroid与SELinux最大的不同在于SEAndroid对Android系统中的Binder做来了适配。进入adb shell 之后可以通过getenforce命令来查看其是否应用。root之后可以通过setenforce 0关闭SEAndroid。但是目前好像关闭了这一功能。
理解SEAndorid的概念不得不提到DAC 和 MAC。
1.1 DAC (Discretionary Access Control,自主访问控制)
DAC是传统的Linux的访问控制方式,DAC可以对文件、文件夹、共享资源等进行访问控制。 在DAC这种模型中,文件客体的所有者(或者管理员)负责管理访问控制。DAC使用了ACL(Access Control List,访问控制列表)来给非管理者用户提供不同的权限,而root用户对文件系统有完全自由的控制权。
通俗的说就是,小明如果建立的某个文件他就对这个文件拥有绝对的控制权,他能够自主的控制其他人对该文件的权限。一个文件权限有读(r)写(w)执行(x)三种。我们可以通过ls -l 这个命令看到各个文件的权限情况。然后通过 chmod 这个命令可以指定这个其他人对这个文件的权限。(chmod 777 1.txt 这个命令大家应该都明白就不细说了)
但是这个机制有个不好的地方就是root用户可以控制任意文件的权限,可以为所欲为。而且控制粒度较粗,如果我只想让另一个人读我的文件,而这个人跟我不是同一用户组,我只能通过chmod XX4 XX 才能达到这一目的,但是这样的话其他任何人都可以读我的文件。所以说它粒度比较粗。
1.2 MAC (Mandatory Access Control,强制访问控制)
所以Linux就引入了MAC机制,即强制控制访问。 MAC核心思想:即任何进程想在SELinux系统中干任何事情,都必须先在安全策略配置文件中赋予权限。凡是没有出现在安全策略配置文件中的权限,进程就没有该权限。这个机制相当于一个白名单,这个白名单上配置了所有进程的权限,进程只能做白名单上权限内的事情,一旦它想做一个不属于它权限的操作就会被拒绝。
MAC不再像DAC一样简单的把进程分为root others等,而是每个进程(Subject,主体)和文件(Object,客体)都配置了一个类型(Type),当一个进程去操控(读写等)一个文件时,系统会检测该进程类型是否有对该文件类型的操作权限。
通过命令ps -Z 可以查看进程的安全label,ls -Z 可以看到文件的label(安全上下文)。
比如进程安全上下文中的init进程,他的type为init,下面的进程的type为kernel。(其实进程的type也被称为Domain )
文件安全上下文中的 123.txt 的 type为 tootfs。
(进程和文件安全上下文label格式为 user:role:type:security_level 中的其它几列不用管。这个涉及到SELinux中其它几种访问控制模型,在SEAndroid中我们只用关心他的type就好,比如init进程的 u:r:init:s0,我们只用知道他的type为init。)
知道进程和文件的安全上下文,那具体是怎么通过他们的安全上下文来控制权限的呢?
在手机上有个文件叫做sepolicy,这个文件就是SEAndroid的安全策略配置文件,里面有所有进程的权限配置,进程只能进行它的权限规定内的操作。这个文件就有root权限也删不掉。把这个文件的内容dump出来后会发现里面有好多条规则(我逆过魅族的4000条,三星的20000条)。看两条例子。
allow untrusted_app system_app_data_file : file { read }
allow zygote sdcard_type : file { read write creat rename }
它的具体格式为:allow Domain Type : Class { Permission } (Domain 是指进程的type)
通过这个格式解读上面的三条规则就是,
1. 允许 untrusted_app类型的进程对 system_app_data_file类型的文件进行read。
2.允许zygote类型的进程对sdcard_type的file进行 read write creat rename。
所以MAC控制方式是这个样子的:当一个进程去操作一个文件的时候,系统会去检测这个进程和文件的上下文,看看这个进程的所属的type有没有对这个的文件的type操作的权限。比如:zygote如果要去读sdcard上的一个文件,这个文件的type为sdcard,zygote的type(Domain)为zygote, 系统去检测看看发现这条规则 allow zygote sdcard_type : file { read write creat rename }。那么这个操作就会被允许执行。zygote要是想删除一个sdcard上的文件,系统发现对应的规则里没有delete,那么就会被deny。(上面的两条规则和这个例子是我自己编的,只是为了说明情况,真实情况下zygote是有权限删除sdcard上的文件的。)
DAC和MAC是同时作用的,一个操作会先后根据DAC和MAC检测完再去执行,不满足任何一个机制的条件都会被拒绝。
2 Hack SEAndroid
上面一节解释了SEAndroid的工作原理,这下知道为什么zygote的root权限并不能为所欲为了,但是如何去更改SEAndroid的规则,扩大zygote的权限。直接更改sepolicy是不行的,因为sepolicy在boot.img里面,每次开机都会重写读取sepolicy这个文件,无法更改成功。
所以要直接解压boot.img替换里面的sepolicy然后重打包。Linux上有一套解压打包工具,windows解压工具为Android-Image-Tools-windows.zip 先找到手机厂商的官方ROM刷机包,找到boot.img解压。里面有个文件是sepolicy。修改sepolicy然后替换它重新打包刷入手机。(好吧其实蛮复杂的,但是我觉得大多数人可能用不到就先这样写吧,以后有需要的话会详细写。本来打算上传自己工具,不知道怎么上传文件。。。 我找不到我工具的链接了,可以去这里找找))
https://github.com/xmikos/setools-android
1.sepolicy-inject:插入规则
2.sesearch:反编译sepolicy
3.seinfo: 查看sepolicy版本
修改sepolicy的命令:push到手机上 直接输入./(相应文件)即可查看其使用方式 (下面是我插入的其中一条命令)
./sepolicy-inject -s zygote -t labeledfs -c filesystem -p remount,getattr,relabelto,transition,quotamod,unmount -P /sepolicy -o /sdcard/sepolicy1
https://forum.xda-developers.com/showthread.php?t=2073775
博客是学习的起点而不是终点。。。这篇文章只是入门SEAndroid,目的性较强,只讲了主要部分,很多内容没有涉及。深入了解SEAndroid的话可以去看看老罗的文章。
**最后, 同学点个赞吧!!! 加个关注好么**
参考链接:
SEAndroid安全机制简要介绍和学习计划 强烈推荐老罗
SEAndroid策略分析 推荐
Android的安全机制
深入理解SELinux