详解Android系统中的root权限获得原理
前言
一直很好奇android root的原理,恰好最近碰到了一个跟android默认带root权限的问题,这里顺便记录一下android系统root的原理。
原理
android是基于llinux内核的开源操作系统,与ubuntu系统类似,所以在android里获取root权限其实和在linux系统下获取root权限是一回事。在linux系统下获取root权限的方法是在命令行执行sudo或者su,接下来输入提权密码就可以获取root权限了。android系统其实也是这样,例如应用层程序开发,在root过的手机上运行root权限的代码如下所示:
process process = runtime.getruntime().exec("su"); dataoutputstream os = new dataoutputstream(process.getoutputstream()); ...... os.writebytes("helloworld!\n"); os.flush();
我们可以看到,android应用程序获取root权限也是需要执行su命令,因此android能够root的密码都在su程序上。但是,android本身是不想让你获取root权限的,因此大部分手机出厂都是user版本,默认是不带su这个二进制程序的。所以你想获取android的root权限,第一步就是要把编译好的su文件拷贝到android手机的/system/bin或/system/xbin目录下(为什么要拷贝到/system目录下,是因为这个分区是没有nosuid限制的,同时/system/bin和/system/xbin又都是系统环境变量path里的路径,可以直接执行su)。我们先假设你可以把编译好的su程序放在xbin或者bin目录下,接下来你可以在android手机的adb shell或者串口下输入su提权了。
linux命令行下输入su之后,是需要输入root密码才能够提权的,但是android里的su和linux里的su是不一样的,android里的su是不靠验证密码的,而且需要验证你之前的权限是什么。意思是,如果你是root用户,那你可以通过su切换到别的用户,比如shell、wifi、audio等。但是如果你是root之外的其他用户,就不能切换到root了,会提示你permission denied。也就是说,用root运行su才有用,但是这个时候我没还有root权限怎么办?这就是接下来要讨论的问题。
我们在ubuntu下查看/usr/bin/passwd文件的权限,如下图所示:
这个文件的权限比较特殊,linux用户一般都知道文件分为r、w、x权限,那这个s是神马意思呢?这里回答一下,s代表当任何一个用户执行该文件的时候都拥有文件所有者的权限,这文件所有者是root。简单来说,就是不管谁执行这个文件,他执行的时候都是以root身份来执行的。
看到这里,大家是不是都有思路了,也就是说,即使我不是root用户也可能以root用户的身份来执行程序,那么我把一个所有者是root的su程序权限标志位设置为-rwsr-xr-x,那么不管是谁执行它,都是以root身份执行。这就牛逼了,su果断可以执行成功,那你也就可以顺利的获取root权限了。
破解
原理都清楚了,那root的过程其实就是分两步:
1. 把一个所有者是root的su拷贝到android手机上。
2. 把su的权限标志位设置成-rwsr-xr-x。
写成代码大概如下所示:
cp /sdcard/su /system/xbin/ chown root:root /system/xbin/su chmod 4755 /system/xbin/su
代码看起来很简单,但是想真正的运行成功,以上代码每一句都需要root权限执行。我擦,一下回到*,跟先有鸡还是先有蛋的问题类似,代码运行需要root权限,而代码本身的目的就是获取root权限,成了一个封闭的死循环了。但是所幸android系统有bug,因此就给了你打破这个死循环的机会。
打破的方法就是找一个本身已经有root权限的进程来运行这个3行的shell脚本,这样脚本就可以顺利执行了。但是已经有root权限的进程都是出厂时候就装到手机上的,代码写死了,你没法控制它执行自己的代码啊,这个时候就需要查找漏洞了。例如android2.3 root权限的zergrush漏洞就是利用一个拥有root权限的进程栈溢出漏洞。具体利用漏洞的方法大家就可以自行google了。
防止root
通过上述分析,我们可以简单的理解,解决android系统能够su提权的方法就是把su文件干掉就可以了。