本文将从几个方面,由浅至深地讲述ROOT到底是什么东西?
一. ROOT权限简单介绍
二.为什么需要ROOT
三. ADBD的ROOT权限
四.深入源代码
ROOT权限简介:
ROOT权限是Linux内核中的最高权限,如果你的身份是ROOT,那么你就具有了ROOT权限。有了最高权限,你就可以为所欲为,换句话说,如果恶意程序获取到了ROOT权限,那么就可以肆意地破坏你的手机,获取的隐私...所以厂商一般在生产手机的时候,不会提供给用户ROOT权限,官方宣称是为了保护用户手机的安全,然后装了一堆开机自动启动,而用户这辈子也用不到也卸载不了垃圾软件(相信使用安卓的同学们都懂我的意思),而苹果所说的越狱,也就是获取ROOT权限。
为什么需要获取ROOT权限?
苹果用户获取ROOT权限,是为了可以免费安装各种软件,以及为了获取更加灵活的操作体验,苹果不会安装一堆恶心的软件;而安卓普通用户获取ROOT权限,最大的目的就是为了卸载这些恶心的自带软件,安卓极客用户则是为了各种折腾安卓手机,安卓开发人员是为了得到日志文件,分析BUG。
ADBD的ROOT权限:
ADBD是什么?相信大家都看过,IT男把手机连上电脑,然后不知怎么的弹出一个黑乎乎的窗口,上面有一排排白色的英文字母,然后帅气的敲击着键盘(一般敲击 adb shell,然后进入手机),啪啪几下,可以帮你解决一些手机的问题。这个可以和手机交互的进程就是ADBD。这就好比,你去朋友家玩,然后你朋友家比较高端,进大门之前有个可视对讲机,那么你首先通过对讲机呼叫朋友(敲击adb shell),看看在不在家(手机是否相应adb shell这个命令),如果朋友在家,那么就会通过对讲机为你开门(成功进入手机中),提供这个服务的可视对讲机就相当于ADBD。说白了,ADBD就是可以为你提供一种进入手机内部的服务通道。
那么为什么需要ADBD具有ROOT权限?这就涉及到另一个与ROOT息息相关的东西——su。
我们开机之后,使用手机的身份就是一个普通用户(user),如果执行su,那么就可以直接切换到ROOT身份。就像仙剑奇侠传三里面的景天,是个凡人,法力有限,但是大家都知道,他的前世是飞蓬将军,法力高强,天界无人能敌,只有魔界至尊重楼可以与他一较高下,当他们来到天庭的时候,玉帝施法,让景天直接切换成飞蓬将军,于是他就有了飞蓬将军的记忆和法力,与重楼又一次大战。su就是这样一个神奇的命令。
高通平台上,su的相关代码位于: LINUX/android/system/extras/su/su.c中
其实我们所说的越狱或者ROOT,就是把su安装到手机里面 /system/bin目录下,并把它的权限设置为4755,那么某些程序需要ROOT权限的时候,就可以通过su切换到ROOT身份,然后去执行,因此一般被ROOT的手机都会安装一个“超级用户”这样的应用,就是用于管理哪些软件可以切换到ROOT身份,哪些不可以,保证用户安全,这个想法是很好很天真,对于正规的软件,人家按照你的路子来,不正规的软件,你一个小小的超级用户的应用,岂能挡我获取ROOT,虐不死你。
那么为什么需要ADBD获取ROOT权限呢?经过上面的讲解大家应该能猜到,如果ADBD有ROOT权限,就可以通过adb 工具,为所欲为,而又不留下痕迹(不安装su),可以删除自带垃圾软件,获取任意目录的文件,安全性较高。笔者就是通过这种方式获取一些系统级别文件。
深入代码:
看了上面的文字,也许很多人会有这样的想法,原来ROOT一个手机这么简单?错!一点也不简单。
首先:/system分区是只读的文件系统,即你无法往system分区中写入任何东西,其次就算你侥幸把su安装到/system/bin下,你也没法修改它的权限为4755,再者,即使你侥幸把su的权限设为4755,你也逃不过有些手机的反root机制(即检测到有文件的权限为4755,就删除)。
首先我们来看看su的部分代码:
- /* Until we have something better, only root and the shell can use su. */
- myuid = getuid();
- if (myuid != AID_ROOT && myuid != AID_SHELL) {
- fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
- return 1;
- }
- if(argc < 2) {
- uid = gid = 0;
- } else {
- int gids_count = sizeof(gids)/sizeof(gids[0]);
- extract_uidgids(argv[1], &uid, &gid, gids, &gids_count);
- if(gids_count) {
- if(setgroups(gids_count, gids)) {
- fprintf(stderr, "su: failed to set groups\n");
- return 1;
- }
- }
- }
- if(setgid(gid) || setuid(uid)) {
- fprintf(stderr,"su: permission denied\n");
- return 1;
- }
- /* Default exec shell. */
- execlp("/system/bin/sh", "sh", NULL);
Android系统启动的时候,ADBD是ROOT权限,只是后来被降级了,判断是否降级的函数是should_drop_privileges()这个函数:
- static int should_drop_privileges() {
- #ifndef ALLOW_ADBD_ROOT
- return 1;
- #else /* ALLOW_ADBD_ROOT */
- int secure = 0;
- char value[PROPERTY_VALUE_MAX];
- /* run adbd in secure mode if ro.secure is set and
- ** we are not in the emulator
- */
- property_get("ro.kernel.qemu", value, "");
- if (strcmp(value, "1") != 0) {
- property_get("ro.secure", value, "1");
- if (strcmp(value, "1") == 0) {
- // don't run as root if ro.secure is set...
- secure = 1;
- // ... except we allow running as root in userdebug builds if the
- // service.adb.root property has been set by the "adb root" command
- property_get("ro.debuggable", value, "");
- if (strcmp(value, "1") == 0) {
- property_get("service.adb.root", value, "");
- if (strcmp(value, "1") == 0) {
- secure = 0;
- }
- }
- }
- }
- return secure;
- #endif /* ALLOW_ADBD_ROOT */
- }
- if (should_drop_privileges()) {
- drop_capabilities_bounding_set_if_needed();
- gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET,
- AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
- AID_NET_BW_STATS };
- if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
- exit(1);
- /* then switch user and group to "shell" */
- if (setgid(AID_SHELL) != 0) {<span style="white-space:pre"> </span>//曾经的漏洞,被封住了
- exit(1);
- }
- if (setuid(AID_SHELL) != 0) {<span style="white-space:pre"> </span>//曾经的漏洞
- exit(1);
- }
- D("Local port disabled\n");
- }
ROOT不是那么轻易的,现在有很多已知的漏洞,但是都被封锁了,所有不是每个root工具都能root成功的,要看它采用的是什么方法来ROOT。