CubieBoard中文论坛

 找回密码
 立即注册
搜索
热搜: unable
查看: 12161|回复: 4

Android 如何永久性开启adb 的root权限

[复制链接]
发表于 2015-5-20 12:00:29 | 显示全部楼层 |阅读模式
首先:/system分区是只读的文件系统,即你无法往system分区中写入任何东西,其次就算你侥幸把su安装到/system/bin下,你也没法修改它的权限为4755,再者,即使你侥幸把su的权限设为4755,你也逃不过有些手机的反root机制(即检测到有文件的权限为4755,就删除)。

首先我们来看看su的部分代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    /* 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;  
       }  


这句话告诉我们,如果执行su的不是ROOT或者SHELL用户,那就直接退出,说明切换身份时候,你必须是这两个用户,还好我们用adb shell进入,是SHELL用户,好险啊。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    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;  
                }  
            }  
        }  


判断执行su的时候,有没有其它参数,我们只是执行su,即argc < 2成立,su也可以切换成其它用户(argc > 2,详细看su命令的使用),这时候,uid 和 gid 都被设置为0 。即ROOT用户的ID号和组号

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    if(setgid(gid) || setuid(uid)) {  
            fprintf(stderr,"su: permission denied\n");  
            return 1;  
       }  


来了来了,就是它,这就是我们最终的目的,把我变身成飞蓬将军,如果一切顺利,你就可以变身成功了(切换ROOT成功)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    /* Default exec shell. */  
        execlp("/system/bin/sh", "sh", NULL);  


每次su之后,就会变成root#,然后就可以通过控制台继续敲命令,但是不同的是,你已经是ROOT了,权限已经很大了。

Android系统启动的时候,ADBD是ROOT权限,只是后来被降级了,判断是否降级的函数是should_drop_privileges()这个函数:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    static int should_drop_privileges() {  
    #ifndef ALLOW_ADBD_ROOT  
        return 1;  
    #else /* ALLOW_ADBD_ROOT */  


首先判断是否定义了ALLOW_ADBD_ROOT,如果系统都不允许你ROOT,就直接返回1,下面什么都不看了,就像找工作的时候,不管你多么厉害,如果你第一条要求都不符合,就直接把你pass了,说什么都没用,够狠的。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

      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;  


下面就是获取系统的属性,判断是否打开ROOT权限,可以看到如果ro.kernel.qumu 这个属性被置为了,没关系再给你一次机会,判断ro.secure是否也是1,如果是,对不起你无法获得root权限,我要把secure置为1了(secure为1意味着要降级,后面会讲解),接着:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

           // ... 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;  
                }  
            }  
        }  
    }  


哈哈,又给了你一次机会,我再来判断ro.debuggable是不是1,如果不是,对不起,我必须要降级,否则再给你一次机会,判断service.adb.root这个属性的值,如果也是1,那么就不降级,一般在编译ROM版本的时候,会同事编译两个版本,一个是工程版本,是具有ROOT权限的ADBD,这样方便开发者调试系统,另一个就是我们用户用的版本,叫user版本,这个是没有ROOT权限的,可以看到,就是通过property_get一系列属性来判断是否降级。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

        return secure;  
    #endif /* ALLOW_ADBD_ROOT */  
    }  


最后,返回secure即可。可以看到最后决定是否降级的变量就是secure,所有如果有源代码的话,只有最后将secure赋值为0,不管什么版本,最后都是ROOT权限。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    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");  
        }   


从这段代码可以看到,如果should_drop_privileges返回1,那么就可以降级了,降级函数为setgid(AID_SHELL)和setuid(AID_SHELL),曾经有黑客利用一些方法,使得setgid和setuid执行失败,即降级失败,以前的代码中是没有exit的,那么当setuid和setgid执行失败之后,就不会降级。

ROOT不是那么轻易的,现在有很多已知的漏洞,但是都被封锁了,所有不是每个root工具都root.


转至:http://blog.csdn.net/memoryjs/article/details/39023729
回复

使用道具 举报

发表于 2015-5-20 16:20:00 | 显示全部楼层
感谢楼主,不明觉厉
回复 支持 反对

使用道具 举报

发表于 2015-5-21 09:07:34 | 显示全部楼层
牛逼了
回复 支持 反对

使用道具 举报

发表于 2015-5-22 21:13:35 | 显示全部楼层
翼京/ka 发表于 2015-5-20 16:20
感谢楼主,不明觉厉

那我也来个“火前留名”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|粤ICP备13051116号|cubie.cc---深刻的嵌入式技术讨论社区

GMT+8, 2024-4-19 17:39 , Processed in 0.022065 second(s), 15 queries .

Powered by Discuz! X3.4

© 2001-2012 Comsenz Inc. | Style by Coxxs

返回顶部