zoukankan      html  css  js  c++  java
  • Adb分析及获取root权限

    Adb的全称为Android Debug Bridge,起到通过PC对Android系统的调试桥的作用,是一个多用途的工具,它能够执行多种命令,还能提供一个shell。这儿简单介绍一下Adb的代码结构,并在某些情况下我们可以获取root权限。

    Adb的代码在system/core/adb里,它的入口函数很直接了当:

    int main(int argc, char **argv)
    {
    #if ADB_HOST            //代码被ADB_HOST宏分成两部分,一部分是宿主,即被ADB_HOST定义包括的部分,运行在Windows或Linux系统上。另一部分是目标,即Android系统上的deamon程序。
        adb_sysdeps_init();
        adb_trace_init();
        D("Handling commandline()
    ");
        return adb_commandline(argc - 1, argv + 1);
    #else
        /* If adbd runs inside the emulator this will enable adb tracing via
         * adb-debug qemud service in the emulator. */
        adb_qemu_trace_init();
        if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
            adb_device_banner = "recovery";
            recovery_mode = 1;
        }
    
        start_device_log();
        D("Handling main()
    ");
        return adb_main(0, DEFAULT_ADB_PORT);
    #endif
    }

    先看宿主代码的路径,我们看到它进入了adb_commandline()函数,这里主要是负责解析参数并执行相应的命令,注意这儿在执行命令之前还有一个启动本地服务的动作:

        if (is_server) {
            if (no_daemon || is_daemon) {
                r = adb_main(is_daemon, server_port);  //Linux平台
            } else {
                r = launch_server(server_port);  //Windows平台
            }
            if(r) {
                fprintf(stderr,"* could not start server *
    ");
            }
            return r;
        }


    这儿会区分宿主平台是Linux还是Windows,他们的服务形态是不一样 的。我们可以使用adb start-server, adb kill-server这样的命令原因在此。

    在本地服务启动前会有一些初始化工作,例如USB的初始化:

    #if ADB_HOST
        HOST = 1;
        usb_vendors_init();
        usb_init();
        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
    
        char local_name[30];
        build_local_name(local_name, sizeof(local_name), server_port);
        if(install_listener(local_name, "*smartsocket*", NULL)) {
            exit(1);
        }
    #else

    因为adb是通过USB 进行socket通信,以adb devices的命令执行过程分析如下:

    1. 组织命令格式,

        if(!strcmp(argv[0], "devices")) {
            char *tmp;
            snprintf(buf, sizeof buf, "host:%s", argv[0]);  //命令格式为:host:devices
            tmp = adb_query(buf);                           //发送命令并返回命令执行结果
            if(tmp) {
                printf("List of devices attached 
    ");
                printf("%s
    ", tmp);                        //打印结果
                return 0;
            } else {
                return 1;
            }
        }

    2. 在adb_query()函数中调用adb_connect()函数发送socket数据,返回后再调用adb_close()关闭socket连接


    下面再来分析目标机器即Android上的adbd守护进程,在刚才的入口函数中,它直接进入了adb_main()函数,并传入DEFAULT_ADB_PORT  5037作为默认端口。在adb_main()函数里进行了一系列初始化动作如,USB,端口监听,运行级别,权限设置等,最后进入到事件循环中等待连接(这儿使用epoll机制)。

    fdevent_loop();


    其中我们对运行级别比较感兴趣,一般情况下我们的adb都是运行在shell用户下,而事实上,adb.c中的代码都是以root权限运行的,以完成部分初始化工作,直到执行了下面的代码:

    if (should_drop_privileges()) {
        ......
            if (setgid(AID_SHELL) != 0) {
                exit(1);                        //这儿曾经是个漏洞,没有检查返回值,可以被某些恶意软件利用来破解root权限
            }
            if (setuid(AID_SHELL) != 0) {
                exit(1);
            }


    它被强行将为shell用户,失去了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 */
    }


    首先考虑ALLOW_ADBD_ROOT宏,这是编译系统决定的,eng版本会打开该宏,其次我们看到变量secure初始值为0,但是在检查了一些属性之后,它变成了1,导致权限降级。而如果ro.debuggable激活,service.adb.root也为1的话,我们还是root权限。在userdebug版本中我们可以在shell下执行:

    setprop service.adb.root 1

    然后杀死并重启adbd守护进程,来提升root权限。


    adb里面有个root命令,可以用来获取root权限。Android守护进程adbd启动时,会调用create_local_service_socket()创建socket套接字,

    fd = service_to_fd(name);

    在service_to_fd(name)函数里,有各种命令的处理方法,如root命令:

    else if(!strncmp(name, "root:", 5)) {
            //ret = create_service_thread(restart_root_service, NULL);
            ret = create_service_thread(restart_root_service, (void *)(name + 5));
        } 

    它在一个新线程里面执行restart_root_service()函数,原始的调用中参数为NULL,我们可以添加一个密码参数,使得该命令只有加上正确的密码才能执行。

    void restart_root_service(int fd, void *cookie)
    {
        char buf[100];
        char value[PROPERTY_VALUE_MAX];
    
        if (getuid() == 0) {                //本来就运行在root用户下
            snprintf(buf, sizeof(buf), "adbd is already running as root
    ");
            writex(fd, buf, strlen(buf));
            adb_close(fd);
        } else {
            property_get("ro.debuggable", value, "");
            if (strcmp(value, "1") != 0) {              //始终绕不过的一个只读属性
                snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds
    ");
                writex(fd, buf, strlen(buf));
                adb_close(fd);
                return;
            }
    
            property_set("service.adb.root", "1");         //恭喜你拥有root了
            snprintf(buf, sizeof(buf), "restarting adbd as root
    ");
            writex(fd, buf, strlen(buf));
            adb_close(fd);
    
            // quit, and init will restart us as root
            sleep(1);
            exit(1);
        }
    }


  • 相关阅读:
    TCP协议
    各相机品牌型号分类
    思科华为命令对比
    网工笔记(一)
    数学笔记
    word快捷键汇总
    请个假
    word笔记
    ScrollView不能到顶部的解决方法
    Gridview 显示成正方形
  • 原文地址:https://www.cnblogs.com/james1207/p/3260481.html
Copyright © 2011-2022 走看看