目录

1、adbd守护进程

2、adbd权限降级

3、adbd命令解析

1)adb shell

2)adb root

3)adb reboot

4、案例

1)案例之实现不需要执行adb root命令自动具有root权限

2)案例之实现不需要RSA认证直接能够使用adb shell命令


adb源码的架构,其实在system/packages/modules/adb/中有注释,如下两个方向:

  • PC主机与adb设备的拓扑图

根据下面一段文字的介绍,android设备的adb主要靠守护进程adbd来实现,具体代码实现是在Daemon里面。

1、adbd守护进程

adbd作为android设备的守护进程,android.bp文件定义如下:

回到adbd主函数中调用adbd_main函数里面,源码如下:

//aosp/packages/modules/adb/daemon/main.cpp
int adbd_main(int server_port) {//...省略...//重点1:auth_required为true表示进行RSA校验,其默认值根据ro.adb.secure
#if defined(__ANDROID__)bool device_unlocked = android::base::GetProperty("ro.boot.verifiedbootstate", "") == "orange";if (device_unlocked || __android_log_is_debuggable()) {
#if defined(__ANDROID_RECOVERY__)auth_required = false;  // Bypass authorization when the device transitions to
#else// If we're on userdebug/eng or the device is unlocked, permit no-authentication.auth_required = android::base::GetBoolProperty("ro.adb.secure", false);
#endif}
#endif//重点2:是否进行权限降级
#if defined(__ANDROID__)drop_privileges(server_port);
#endif
#if defined(__ANDROID__)// A thread gets spawned as a side-effect of initializing the watchdog, so it needs to happen after we drop privileges.watchdog::Initialize();
#endif//重点3:证书权限相关校验,如果auth_required为false其adb/daemon/auth.cpp直接返回不需要校验// adbd_auth_init will spawn a thread, so we need to defer it until after selinux transitions.adbd_auth_init();bool is_usb = false;
#if defined(__ANDROID__)if (access(USB_FFS_ADB_EP0, F_OK) == 0) {// Listen on USB.usb_init();is_usb = true;}
#endif// If one of these properties is set, also listen on that port.// If one of the properties isn't set and we couldn't listen on usb, listen on the default port.std::vector<std::string> addrs;std::string prop_addr = android::base::GetProperty("service.adb.listen_addrs", "");if (prop_addr.empty()) {//...省略...} else {addrs = android::base::Split(prop_addr, ",");setup_adb(addrs);}//重点3:关键日志,adbd启动,如果没有这行日志,说明adbd根本无法使用LOG(INFO) << "adbd started";D("adbd_main(): pre init_jdwp()");init_jdwp();D("adbd_main(): post init_jdwp()");D("Event loop starting");//重点4:进入fd事件轮询,即监听pc端发送过来的数据,最终传递在daemon_service_to_fd函数中进行解析fdevent_loop();return 0;
}

总结如上adbd守护进程主函数大致流程如下:

  • 设置auth_required状态,为true表示进行RSA校验,其默认值根据ro.adb.secure。重点,我们可以定制ro.adb.secure属性的值来实现不需要设备授权直接使用adb命令
  • 通过drop_privileges方法来实现权限降级
  • 通过setup_adb设置地址(串口号?),这里除了判断是usb链接还是wifi链接之外,还处理多台usb设备之间的关系
  • 进入fdevent_loop事件轮询,监听PC adb端发送过来的命令

2、adbd权限降级

前面已经介绍了drop_privileges来实现权限降级,那么什么是权限降级呢?这涉及到linux dac机制,在android_filesystem_config.h 文件中定义了大量的权限等级:

AID_XXX定义了android系统中基本能分解的所有用户组和权限(0-100000)。其中AID_ROOT等于0被作为最高用户组。咨询AI这其实就是Linux DAC的实现机制。

回到drop_privileges函数如下内容:

static void drop_privileges(int server_port) {ScopedMinijail jail(minijail_new());// Add extra groups:// AID_ADB to access the USB driver// AID_LOG to read system logs (adb logcat)// AID_INPUT to diagnose input issues (getevent)// AID_INET to diagnose network issues (ping)// AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)// AID_SDCARD_R to allow reading from the SD card// AID_SDCARD_RW to allow writing to the SD card// AID_NET_BW_STATS to read out qtaguid statistics// AID_READPROC for reading /proc entries across UID boundaries// AID_UHID for using 'hid' command to read/write to /dev/uhid// AID_EXT_DATA_RW for writing to /sdcard/Android/data (devices without sdcardfs)// AID_EXT_OBB_RW for writing to /sdcard/Android/obb (devices without sdcardfs)// AID_READTRACEFS for reading tracefs entriesgid_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, AID_READPROC,     AID_UHID,     AID_EXT_DATA_RW,AID_EXT_OBB_RW,   AID_READTRACEFS};minijail_set_supplementary_gids(jail.get(), arraysize(groups), groups);// Don't listen on a port (default 5037) if running in secure mode.// Don't run as root if running in secure mode.if (should_drop_privileges()) {//...省略...//核心代码:通过minijail_change_gid切换用户组ID为AID_SHELL,属于Linux DAC降低权限minijail_change_gid(jail.get(), AID_SHELL);minijail_change_uid(jail.get(), AID_SHELL);//核心代码:通过minijail_enter执行最终的沙箱隔离操作,属于Linux DAC机制// minijail_enter() will abort if any priv-dropping step fails.minijail_enter(jail.get());//...省略...D("Local port disabled");} else {//核心代码:通过minijail_enter执行最终的沙箱隔离操作,默认是ROOT?// minijail_enter() will abort if any priv-dropping step fails.minijail_enter(jail.get());//防错处理,如果变量root_seclabel设置的selinux安全上下文不是0,即不是root用户,强制属性service.adb.root的在值为0if (root_seclabel != nullptr) {if (selinux_android_setcon(root_seclabel) < 0) {// If we failed to become root, don't try again to avoid a// restart loop.android::base::SetProperty("service.adb.root", "0");LOG(FATAL) << "Could not set SELinux context";}}}
}

如上代码总结如下:

  • 通过should_drop_privileges来判断是否需要进行权限降级,返回true进行权限降级
  • 进行权限降级:切换用户组为AID_SHELL,来达到降级的目的
  • 不进行权限降级:没有地方去切换用户组等级,默认为root组?

接下来继续分析一下should_drop_privileges是如何来判断需要进行权限降级?

  • 所以最后的核心:最后通过下一小节可以了解到执行adb root之后就会设置属性service.adb.root为1;执行adb unroot之后就会设置属性service.adb.root为0,即adb root之后,adb终端重启并进入最高用户权限等级。

3、adbd命令解析

PC主机发送过来的adb xxx命令,最后由守护进程adb/daemon/services通过套接字或者fd的方式来接收adb相关命令,如下代码逻辑:

如上代码,解析几条重要的adb xxx命令之后,通过create_service_thread的方式去启动线程来执行对应的命令。

1)adb shell

daemon_service_to_fd方法解析为adb shell,直接调用ShellService来进行命令参数拼接

这里比较核心的方法StartSubprocess,在adb/daemon守护进程里面基本上通过它来创建子进程,然后用shell作为执行源。

2)adb root

我们执行adb root的时候,会执行如下函数,如果不是debug版本直接返回,如果是debug版本设置service.adb.root属性值为1.

3)adb reboot

adb reboot命令同上,但是这里区分一下,并没有使用终端shell方式,第二个参数为null,cmd直接定义为/system/bin/reboot,即后续直接创建子进程,以reboot文件作为执行源。

4、案例

1)案例之实现不需要执行adb root命令自动具有root权限

根据adbd权限降级和adb root命令执行可以了解如下逻辑:

  • 执行adb root之后:service.adb.root 为1,在drop_privileges中使用了root用户组
  • 执行adb unroot之后:service.adb.root 为0,在drop_privileges中使用了shell用户组

因此如果我们想绕过adb root命令,直接带有root用户组权限,那么可以强制函数should_drop_privileges返回false。如下案例:

2)案例之实现不需要RSA认证直接能够使用adb shell命令

安卓设备通过usb链接电脑之后,我们在开发者模式菜单开启usb调试之后,通常还无法直接通过adb shell链接设备。会弹出如下对话框进行授权

如果我们想跳过这个对话框的显示,那么可以根据adbd守护进程中讲解的,强制属性ro.adb.secure的值为false即可,在debug版本或者解锁版本中,此值如果没有设置默认当成false。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/83064.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/83064.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/83064.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言进阶--动态内存管理

学习数据结构重要的三个部分&#xff1a;指针、结构体、动态内存管理&#xff08;malloc、calloc、realloc、free&#xff09;。 1.为什么存在动态内存分配&#xff1f; 1.空间开辟大小是固定的&#xff1b; 2.数组在声明时&#xff0c;必须指定数组的长度&#xff0c;它所需…

C# 密封类和密封方法

密封(sealed)是C#中用于限制继承和多态行为的关键字&#xff0c;它可以应用于类和方法&#xff0c;提供了一种控制继承层次的方式。 密封类 特点 使用 sealed 关键字修饰的类密封类不能被其他类继承&#xff0c;但可以继承其他类或接口主要用于防止派生所有结构(struct)都是…

thinkpad T-440p 2025.05.31

thinkpad T-440p 2025.05.31 老了退休了&#xff0c;说起来真的可恶现在笔记本的设计师&#xff0c;只有固态硬盘了

WPS自动换行

换行前 换行后 快捷键 第一步&#xff1a;启用「自动换行」功能 选中目标单元格/区域&#xff1a;点击需要设置的单元格&#xff08;或拖动选中多个单元格&#xff09;。开启自动换行&#xff08;3种方式任选&#xff09;&#xff1a; 快捷按钮&#xff1a;在顶部菜单栏点击「…

cuda_fp8.h错误

现象&#xff1a; cuda_fp8.h错误 原因&#xff1a; CUDA Toolkit 小于11.8,会报fp8错误&#xff0c;因此是cuda工具版本太低。通过nvcc --version查看 CUDA Toolkit 是 NVIDIA 提供的一套 用于开发、优化和运行基于 CUDA 的 GPU 加速应用程序的工具集合。它的核心作用是让开发…

【TTS】基于GRPO的流匹配文本到语音改进:F5R-TTS

论文地址&#xff1a;https://arxiv.org/abs/2504.02407v3 摘要 我们提出了F5R-TTS&#xff0c;这是一种新颖的文本到语音(TTS)系统&#xff0c;它将群体相对策略优化(GRPO)集成到基于流匹配的架构中。 通过将流匹配TTS的确定性输出重新表述为概率高斯分布&#xff0c;我们的方…

头歌java课程实验(Java面向对象 - 包装类)

第1关&#xff1a;基本数据类型和包装类之间的转换 任务描述 本关任务&#xff1a;实现基本数据类型与包装类之间的互相转换。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 1.什么是包装类&#xff1b; 2.怎么使用包装类。 什么是包装类 在JAVA中&#x…

实现一个免费可用的文生图的MCP Server

概述 文生图模型为使用 Cloudflare Worker AI 部署 Flux 模型&#xff0c;是参照视频https://www.bilibili.com/video/BV1UbkcYcE24/?spm_id_from333.337.search-card.all.click&vd_source9ca2da6b1848bc903db417c336f9cb6b的复现Cursor MCP Server实现是参照文章https:/…

ES6 深克隆与浅克隆详解:原理、实现与应用场景

ES6 深克隆与浅克隆详解&#xff1a;原理、实现与应用场景 一、克隆的本质与必要性 在 JavaScript 中&#xff0c;数据分为两大类型&#xff1a; 基本类型&#xff1a;Number、String、Boolean、null、undefined、Symbol、BigInt引用类型&#xff1a;Object、Array、Functio…

新闻数据加载(鸿蒙App开发实战)

本案例基于ArkTS的声明式开发范式&#xff0c;介绍了数据请求和onTouch事件的使用。包含以下功能&#xff1a; 数据请求。列表下拉刷新。列表上拉加载。 网络数据请求需要权限&#xff1a;ohos.permission.INTERNET 一、案例效果截图 操作说明&#xff1a; 点击应用进入主页…

办公效率王Word批量转PDF 50 +文档一键转换保留原格式零错乱

各位办公小能手们&#xff0c;我跟你们说啊&#xff01;在办公的时候&#xff0c;咱经常会碰到要把一堆Word文档转成PDF格式的情况&#xff0c;比如说要统一文件格式、保护文档内容或者方便分享啥的。这时候&#xff0c;就需要用到Word批量转换成PDF的软件啦。下面我就给你们好…

一张Billing项目的流程图

流程图 工作记录 2016-11-11 序号 工作 相关人员 1 修改Payment Posted的导出。 Claim List的页面加了导出。 Historical Job 加了Applied的显示和详细。 郝 识别引擎监控 Ps (iCDA LOG :剔除了160篇ASG_BLANK之后的结果): LOG_File 20161110.txt BLANK_CDA/ALL 45/10…

SpringAI系列4: Tool Calling 工具调用 【感觉这版本有bug】

前言&#xff1a;在最近发布的 Spring AI 1.0.0.M6 版本中&#xff0c;其中一个重大变化是 Function Calling 被废弃&#xff0c;被 Tool Calling 取代。Tool Calling工具调用&#xff08;也称为函数调用&#xff09;是AI应用中的常见模式&#xff0c;允许模型通过一组API或工具…

第六十三节:深度学习-模型推理与后处理

深度学习模型训练完成后,如何高效地将其部署到实际应用中并进行准确预测?这正是模型推理与后处理的核心任务。OpenCV 的 dnn 模块为此提供了强大支持,本文将深入探讨 OpenCV 在深度学习模型推理与后处理中的关键技术与实践。 第一部分:基础概念与环境搭建 1.1 核心概念解析…

uniapp开发企业微信小程序时 wx.qy.login 在uniapp中使用的时候,需要导包吗?

在 UniApp 中使用 “wx.qy.login” 不需要手动导包&#xff0c;但需要满足以下条件&#xff1a; 一、环境要求与配置 1&#xfffd; 企业微信环境判断 必须确保当前运行环境是企业微信客户端&#xff0c;通过 “uni.getSystemInfoSync().environment” 判断是否为 “wxwork”…

ONLYOFFICE文档API:更强的安全功能

在数字化办公时代&#xff0c;文档的安全性与隐私保护已成为企业和个人用户的核心关切。如何确保信息在存储、传输及协作过程中的安全&#xff0c;是开发者与IT管理者亟需解决的问题。ONLYOFFICE作为一款功能强大的开源办公套件&#xff0c;不仅提供了高效的文档编辑与协作体验…

Linux系统编程之共享内存

概述 在Linux系统中&#xff0c;共享内存也是一种高效的进程间通信机制&#xff0c;允许两个或多个进程共享同一块物理内存区域。通过这种方式&#xff0c;不同进程可以直接访问和操作相同的数据&#xff0c;从而避免了数据的复制。由于数据直接在内存中共享&#xff0c;没有额…

零知开源——STM32F407VET6驱动Flappy Bird游戏教程

简介 本教程使用STM32F407VET6零知增强板驱动3.5寸TFT触摸屏实现经典Flappy Bird游戏。通过触摸屏控制小鸟跳跃&#xff0c;躲避障碍物柱体&#xff0c;挑战最高分。项目涉及STM32底层驱动、图形库移植、触摸控制和游戏逻辑设计。 目录 简介 一、硬件准备 二、软件架构 三、…

Elasticsearch创建快照仓库报错处理

创建快照仓库报错&#xff1a; 根据报错提示的信息&#xff0c;问题可能出在 Elasticsearch 的配置中。当你尝试创建一个文件系统&#xff08;fs&#xff09;类型的快照仓库时&#xff0c;虽然已经指定了 location 参数&#xff0c;但 Elasticsearch 仍然报错&#xff0c;这通…

服务器如何配置防火墙管理端口访问?

配置服务器防火墙来管理端口访问&#xff0c;是保障云服务器安全的核心步骤。下面我将根据你使用的不同操作系统&#xff08;Linux: Ubuntu/Debian/CentOS&#xff1b;Windows Server&#xff09;介绍常用防火墙配置方法。 ✅ 一、Linux 防火墙配置&#xff08;UFW / firewalld…