Android Native 之 adbd進程分析

?

目錄

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…