Adb分析及获取root权限

本文深入解析ADB(Android Debug Bridge)的代码结构与权限机制,揭示如何在特定条件下获取root权限,包括ADB的工作原理、代码路径分析及在不同平台上的服务启动方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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()\n");
    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()\n");
    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 *\n");
        }
        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 \n");
            printf("%s\n", 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\n");
        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\n");
            writex(fd, buf, strlen(buf));
            adb_close(fd);
            return;
        }

        property_set("service.adb.root", "1");         //恭喜你拥有root了
        snprintf(buf, sizeof(buf), "restarting adbd as root\n");
        writex(fd, buf, strlen(buf));
        adb_close(fd);

        // quit, and init will restart us as root
        sleep(1);
        exit(1);
    }
}


 

 

转载于:https://www.cnblogs.com/james1207/p/3260481.html

### 通过 ADB 命令获取设备 Root 权限的方法 获取设备 Root 权限通常需要确保设备已经完成 Root 操作。以下是使用 ADB 命令获取 Root 权限的几种方法: #### 方法一:通过 `su` 提权 在已 Root 的设备上,可以通过执行 `su` 命令来提升 ADB Shell权限。如果设备尚未安装 `su` 文件,则需要手动推送该文件到系统目录并设置正确的权限。 1. 确保设备已解锁 Bootloader 并完成 Root 操作。 2. 将 `su` 文件推送到设备的 `/system/bin/` 目录: ```bash adb push su /system/bin/ ``` 3. 修改 `su` 文件的权限以允许提权: ```bash adb shell chmod 4755 /system/bin/su ``` 4. 如果提示 `Read-only filesystem`,则需要重新挂载 `/system` 分区为可读写模式: ```bash adb shell mount -o remount,rw /dev/block/mtdblock0 /system/ ``` 5. 验证是否成功获取 Root 权限: ```bash adb shell su -c "id" ``` 如果返回 `uid=0(root)`,则表示已成功获取 Root 权限[^2]。 #### 方法二:修改 `default.prop` 文件 通过修改根目录下的 `default.prop` 文件,可以设置设备的安全属性以允许 ADB 获取 Root 权限。 1. 重新挂载根文件系统为可读写模式: ```bash adb shell mount -o remount,rw rootfs / ``` 2. 使用文本编辑器(如 `vi`)打开 `default.prop` 文件: ```bash adb shell vi /default.prop ``` 3. 修改以下属性值: ```properties ro.secure=0 ro.debuggable=1 persist.service.adb.enable=1 ``` 4. 保存文件并重启设备以应用更改: ```bash adb reboot ``` 5. 验证 ADB Shell 是否具有 Root 权限: ```bash adb shell id ``` 如果返回 `uid=0(root)`,则表示已成功获取 Root 权限[^3]。 #### 方法三:使用 Magisk 提供的 ADB Root 功能 Magisk 是一种现代化的 Root 解决方案,支持通过模块化方式管理 Root 权限。启用 Magisk 的 ADB Root 功能可以简化权限获取过程。 1. 确保设备已安装 Magisk 应用程序。 2. 打开 Magisk 应用程序,进入 `Settings` -> `ADB Integration`。 3. 启用 `Enable ADB Root` 选项。 4. 验证 ADB Shell 是否具有 Root 权限: ```bash adb shell id ``` 如果返回 `uid=0(root)`,则表示已成功获取 Root 权限。 ### 注意事项 - 设备解锁 Bootloader 和 Root 操作可能会导致保修失效,请谨慎操作。 - 修改系统文件可能导致设备不稳定或无法启动,请确保备份重要数据。 - 不当操作可能导致设备变砖,建议仅在了解相关风险的情况下进行尝试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值