[資安研討會] 006 HITCON 2025 Day1 <重點整理> 破解 Pixel 8:利用未公開的 DSP 漏洞繞過 MTE 防護

相關議程精華紀錄聲明

以下議程精華紀錄由 AI 協助整理與重構,內容僅供參考,實際細節請以講者原始演講與官方資料為準。

破解 Pixel 8:利用未公開的 DSP 漏洞繞過 MTE 防護

講者

Billy(Jheng Bing Jhong)Pan Zhenpeng(Peter)
Billy 與 Peter 都是 STAR LABS SG 的 Principal Researcher,長期專注於 Android / iOS / Linux / VM 等行動與系統資安研究,曾在 HITCON、DEF CON、POC、Zer0Con 等研討會發表。

議程重點

1. 背景與動機

  • 研究目標鎖定 Android 14 的 Pixel 8,這台機器上幾乎把主流防護都開好開滿:
    • PAN / PXN(防止 kernel 亂用 user space 記憶體)
    • UAO(限制對 user access helper 的寫入)
    • PAC(指標簽章,抵禦 ROP)
    • MTE(Memory Tagging Extension)
    • KASLR、stack/heap 初始化強化、list 完整性檢查、slab free-list randomization… 等
  • 在本地提權攻擊中,永遠需要一個「攻擊面」作為起點;不同攻擊面影響範圍不同:
    • Universal:例如 Linux kernel unix socketbinderpipe buffer
    • Chipset-specific:如 Mali / Qualcomm GPU driver、Qualcomm DSP
    • Vendor-specific:Samsung 自家 NPU、GPU、KNOX / Defex 等
    • Model / module-specific:只存在於特定機型或個別模組
  • 本場研究的漏洞屬於 Pixel 專屬 DSP 模組 的攻擊面,可視為 module-specific exploit
    • Pixel 使用 Google 自家 DSP(簡稱 GXP),2022 才在 Pixel 7 引入
    • 沒有公開文件、沒有 toolchain、也沒有既有漏洞研究
  • 過去已有許多 GPU / NPU / DSP 相關漏洞研究(Mali、Qualcomm GPU / DSP、Samsung NPU 等),團隊希望把這些經驗「複製」到 GXP 上,看看是否也存在類似問題。

2. 主要問題 / 挑戰

  • GXP 完全沒文件、沒工具鏈
    想分析 DSP firmware 卻沒有 ISA 文件、沒有開發工具,只能從 kernel driver + firmware binary 逆向。
  • 攻擊面被 SELinux 嚴格管控
    • 一般 untrusted_app context 不能直接 open GXP device,卻被允許發送某些 ioctl
    • 顯示一定有中介 server 代為開啟 device → 必須先搞清楚這條路徑
  • 漏洞屬性是「理論上可行」,但不確定實際能利用
    • driver 中出現一個「讓 DMA 寫入 CPU read-only 記憶體」的可能性
    • 如果沒有任何 DSP 端 API 真的會去寫那塊 memory,這就只是紙上談兵
  • 在強化的 Android 環境中串成完整 exploit chain 很難
    • MTE、KASLR、SELinux、各種硬化 config 都在
    • 要從 app → system service → kernel module → root shell,中間每一步都可能被擋
  • 如何穩定控制高權限的 system service(camera provider)
    • 從 app 看不到目標 service 的 PID
    • 在隔離環境下難以直接對特定 process 下手
    • 要找到一種「大致猜到 PID,再強迫它重啟並載入惡意 library」的方法

3. 技術方法 / 解決方案

3-1 攻擊面盤點:為什麼選 GXP DSP?
  • Pixel 中除了常見 GPU 外,還有幾個 Google 自家 driver
    • Pixel HTPU、Pixel GXP、LWIS 等
  • Edge TPU 過去就有公開漏洞(例如 race condition 導致 kernel memory 損壞),證明這類協同處理器 driver 不是沒問題
  • GXP:
    • 新、文件少、沒有公開研究
    • 又是影像處理 pipeline 中核心元件,Google Camera 等系統 app 都會用
      → 在防護都很新而且開滿的 Pixel 8 上,GXP 成為很有吸引力的攻擊面。
3-2 先找得到攻擊面:從 SELinux policy 入手
  • 檢查 SELinux policy 後發現:
    • untrusted_app context 可以對 GXP 做 ioctl,但 不能 open 裝置節點
    • 代表:必須透過某個「中介 server」幫忙 open 後,把 FD 傳給 app
  • 逆向相關 library / service:
    • 在 policy 中發現 edge_tpu_app_server 之類的 server context
    • 逆向 libedge_tpu_clientlibgxp.so 等,看到像 get_dsp_fd() 這種 function
    • 確認流程:app → client lib → edge_tpu app server → 打開 GXP device → 傳回 FD
  • 結論:
    只要能在「被列入 whitelist 的 app / 簽章」中執行我們的 code,就能觸碰到 GXP 攻擊面。
3-3 漏洞本體:GXP mapping 的「write read-only」問題
  • 透過 ioctl(GXP_MAP_BUFFER, …) 可以走到 kernel 中的 gxp_mapping_create()
    • 驅動會根據 user 傳進來的參數:
    • 利用 find_extend_vma() 找到被 import 的 user VMA
    • 從這個 VMA 取得屬性,設定 folio_flags(read / write…)
    • mapping_dir(DMA 方向)卻直接抄 user 傳入的 dir 不做檢查
  • 接著:
    • mapping_dir 會被用來設定 DSP MMU 上這塊 memory 的屬性
    • 如果 user 傳 DMA_BIDIRECTIONAL,DSP 端就會認為這塊 memory 是「可讀可寫」
  • 於是出現關鍵問題:

CPU 這邊把某塊記憶體映成 read-only
但 GXP driver 可以被騙,
把同一塊物理頁在 DSP 的 MMU 上映成 read-write

  • 這就提供了 「write read-only memory」primitive
    • 只要 GXP 有任何 API 會對這塊 buffer 寫東西,就等於繞過 CPU 端的唯讀保護。
3-4 第一次嘗試:模擬 firmware(放棄)
  • 步驟:
    1. 在 driver 中找到載入 firmware 的程式(透過 device tree resource 找到物理位址,devm_ioremap() 映射到 kernel)
    2. 用自寫內核模組 / BPF 把這片 memory dump 出來
    3. 丟進 IDA 逆向,確認裡面有 mailbox / ring buffer 等 DSP 相關符號
    4. 想用 QEMU 之類的工具模擬 CPU + 跑 firmware,進一步找「寫 memory 的 handler」
  • 實際遇到的坑:
    • QEMU 不支援這顆 DSP 的指令集
    • 很多系統暫存器(MSR/MRS 類)不符合手冊行為
    • 沒符號、架構又陌生 → 逆向成本超高
  • 結果:
    幾天後直接放棄,改走「重放攻擊(replay attack)」路線。
3-5 第二次嘗試:Replay Attack + Frida 動態插樁
  • 先找「誰在用 GXP」:
    • 從 SELinux policy & 實作觀察得知:
    • Google Camera、YouTube Music 等 whitelist app 會使用 GXP
    • 選擇最常見、預設內建且一定會調用的 Google Camera 作為觀察目標
  • 在 Google Camera process 裡:
    • 找到一個 share library:libgxp.so
    • 裡面可以看到類似 OpenCL 的介面:create_devicecreate_bufferenqueue… 等
    • 推測:這就是 GXP 版的「使用者態 API」。
  • 使用 Frida
    • 利用 Interceptor.attach() hook 目標 process 的 ioctl
    • 同時列舉 libgxp.so 的所有 exported functions,一一加上 hook
    • 記錄實際拍照 / 開啟 Camera 時,GXP 使用的 call flow與各種參數
  • 收穫:
    • libgxp.so 中找到一個關鍵高階 API:
      類似 gxp_copy_open_named_library_from_buffer() 的函式
    • 透過這個 API,可以觸發之前找到的「可疑 mapping code」,而且 確認 GXP 會對 buffer 寫入內容
  • PoC 實作:
    1. 在 user space 建立一個 read-only 映射頁面,初始化成 0
    2. 把這塊頁面 import 給 GXP,並強塞 DMA_BIDIRECTIONAL
    3. 呼叫上述 copy 函數
    4. 回到 CPU 端檢查這頁記憶體 → 發現被覆寫成 0xAA
      ⇒ 實證:GXP 確實可以寫 CPU 端的 read-only 頁面
3-6 Google 的修補方式
  • 修補後的 driver:
    • 從 host VMA 正確取得 gup_flagsget_user_pages 的 flag)
    • 將其轉換為內部 gci_flags
    • gci_flags 為唯一來源,設定 DMA/MMU 屬性
  • 整體 flow:
    Host address → VMA → GUP flags → GCI flags → MMU mapping
    → user 想用 dir 欺騙 mapping_dir 已經行不通。
3-7 Exploit Chain:從 write read-only 到 kernel module & root
  1. 原本想走 Dirty Pipe 式路線(但被 SELinux 卡住)
    • Dirty Pipe 的經典做法:
      改寫只讀檔(如 libc.so 或 config),劫持高權限 process → 寫入 kernel module → modprobe 載入 → 關 SELinux → root shell。
    • 問題:
      • Dirty Pipe 只需要一般 syscall,沒特殊權限
      • 本漏洞則 必須能「隱身地」操作 GXP device
        → 在 init / system_server 這種 context 中 拿不到 GXP 使用權限
  2. 改走 Camera provider 路線

  • 觀察 SELinux policy:
    • android.hardware.camera.provider 這個 service
      • 可以 open / ioctl GXP device
      • 也可以 open / mmap 某些 vendor 檔案(library)
  • 目標:
    劫持 camera provider,讓它在重啟時載入我們控制的 library。
  1. 如何強迫 camera provider 重啟?(不知道 PID 的情況下)
  • 特性:
    • Camera provider 是開機早期就啟動的 system daemons 之一
    • 開機後這類 daemon 的 PID 會落在一個相對小且穩定的範圍
  • 作法:
    • 由我們控制的 context(有能力殺 process)去 遍歷這個 PID range,逐一送 kill
    • 大部分被殺的是 system daemon,會被 init 自動拉起
    • 在這個過程中也會順便把 camera provider 幹掉,迫使它重啟
  • 限制:
    • 如果系統已跑很久、camera provider 中途 crash 過再重啟,PID 可能跳到很大範圍,這種方法就不穩定。
  1. Library Hijacking & 多階段 payload
  • Stage 1:從 app → write read-only
    • 使用 GXP 漏洞,把某個「camera provider 會在啟動時載入的 library」(例如負責 logging 的 liblog 類型)改成帶有我們 loader 的版本
    • 強迫 camera provider 重啟 → 下次啟動時就會載入被我們修改的 library → 取得 camera provider context 下的程式碼執行
  • Stage 2:在 camera provider 內部再利用 write read-only
    • 再次使用 write read-only primitive,寫入兩類 payload:
      1. 修改 modprobe 相關設定(或特定 config),讓 kernel 在需要載入 module 時會去讀我們控制的位置
      2. 在某個路徑放入「惡意 kernel module」的 binary(reverse shell + 關 SELinux)
    • 利用擁有足夠權限的 process 觸發 modprobe
    • kernel 讀到被改寫的路径,載入我們的 module
  • Stage 3:kernel module
    • 被載入後:
      • 關閉 SELinux
      • 建立 reverse shell,連回攻擊者的 server,取得 root shell
  1. 為什麼 exploit 要跑 5 分鐘?
  • GXP 端提供的 copy 函數行為類似 strcpy
    • 遇到 0x00 就停止
  • 但 shellcode / payload 總是含有大量 0 bytes
    • 不能一次 copy 完整 buffer,不然會斷在第一個 0
    • 只好 一個 byte 一個 byte 重複呼叫,慢慢寫入
  • 加上:
    • 整個 chain 有很多 stage
    • 每一次 DSP ↔ CPU 都要做 memory synchronize
      → 全部疊加起來,完整 exploit 流程大約要跑五分鐘左右。

4. 實驗成果 / 攻擊流程摘要

  • 目標環境
    • 裝置:Google Pixel 8
    • 系統:Android 14
    • 安全機制:MTE / KASLR / 各種 kernel hardening 啟用
  • 攻擊成果
    • 從一個安裝在手機上的 app 開始
    • 透過 GXP DSP 漏洞取得 write read-only primitive
    • 劫持 android.hardware.camera.provider 服務
    • 植入惡意 kernel module,載入後關 SELinux
    • 取得 root shell(reverse shell 回連攻擊者電腦)
  • 漏洞修補 & 負責任通報
    • 2023 年中發現漏洞並開始開發 exploit
    • 2023/9 報給 Google
    • Google 要求提供「可重現的 source-based PoC」,而非單純 binary
    • 2023/11 Google 對外宣佈相關 bug bounty
    • 2024 Q1 左右完成修補並發佈 patch(CVE 編號當時尚未公開)
    • 講者透露這個漏洞日後還會出現在另一條 exploit chain 的研究中

5. 限制與未來方向

  • 漏洞影響面狹窄
    • 只影響具備 Pixel GXP DSP、且具備相同 driver 實作的裝置
    • 更偏向「model / module-specific」的攻擊
  • Exploit 本身較脆弱
    • 依賴 PID range 的特徵來強迫 camera provider 重啟
    • 需 5 分鐘以上執行時間,實務上偏向「高價值目標」才值得這樣操作
  • MTE 的防護邊界
    • MTE 主要防範 緩衝區溢位 / use-after-free 等記憶體破壞
    • 對於:
    • DMA 屬性錯誤
    • 協同處理器 MMU 管理邏輯 bug
      完全無能為力
  • 未來可能方向
    • 更系統地審視各家協同處理器(DSP / NPU / ISP / baseband)的 DMA 及 MMU 流程
    • 在 OS 層加入 runtime consistency check(例如:檢查 DMA 屬性是否與 VMA 權限一致)
    • 安全審查流程中,把「vendor 自研 IP / driver」當成一級攻擊面,而不是附屬。

💡 我的觀察

  • 1. 防禦做得越好,攻擊面就越往「灰暗角落」擠

    • 當 kernel、system server、常見 driver 都被鋪滿 mitigations 之後,攻擊者就會開始鑽進:
    • 各種協同處理器(DSP / NPU / ISP)
    • vendor / model 專屬 driver
    • 這場研究非常典型:不是從 Linux 主線 bug 下手,而是從 Pixel 自家 GXP DSP 打進去
    • 對企業與 OEM 來說,安全審查不能只看「主 SoC + Android 原生部分」,所有自研模組都要列入 Threat Model。
  • 2. MTE 不是萬靈丹,它擋的是「類型」,不是「所有 0day」
    • 很多人看到 MTE 會直覺覺得「那本地提權是不是要絕跡了?」
      這場議程很直接地給出:No
    • 只要攻擊從一開始就不是典型的 buffer overflow / UAF,而是:
    • DMA 屬性錯誤
    • 邏輯漏洞
    • 權限邊界錯配
      → MTE 根本不會出手。
    • 所謂的「bypass MTE」很多時候不是什麼花式繞過,而是 選擇一條 MTE 原本就管不到的路線
      這對 defender 的啟示是:導入硬體防護時,一定要清楚「它保護的是哪一塊」,不要把其他風險當作已解決。
  • 3. Replay 攻擊是 Closed-source 環境下非常實用的研究方法
    • 在沒有文件、沒有 toolchain 的 DSP 上,講者沒有硬幹完整逆向,而是:
    • 利用 SELinux policy 找出誰在用 device
    • 透過 Frida 直接對現實世界「怎麼用 driver」做 trace
    • 把 production app 的實際行為當作「官方 SDK」來複用
    • 這種 replay + hook 的手法對紅隊非常有參考價值:
      不一定要搞懂所有細節,只要能重放系統自己怎麼用,就足以構造 exploit。
    • 相對地,藍隊也應該把「system app 對 kernel driver 的 ioctls」視為關鍵觀測點,
      不尋常的參數模式可能就是 exploit 在跑。
  • 4. 從企業角度:kernel module 仍然是致命後門
    • 這條 chain 最終還是落在 任意載入 kernel module、關 SELinux、開 root shell
    • 對企業裝置或高價值標的來說:
    • 降低或監控 modprobe 行為
    • 嚴格限制自訂 module 的存在(甚至關掉 module support)
    • 對 boot chain、system image 做完整性保護
      仍然是非常關鍵的防線。

整體來說,這場議程展示的是:
在「幾乎所有主流防護都打開」的 Pixel 8 上,攻擊者依然可以透過一顆幾乎沒人碰過的 DSP,一路打到 kernel root。
對做防禦的人而言,這提醒我們:真正的攻擊面,常常躲在你以為「只是加速影像處理的小 IP」裡面。

飛飛
飛飛

講師學歷:臺科資工所、逢甲資工系畢業。
技術專長:OSINT、滲透測試、網站開發、專業易懂教育訓練。
證照書籍:OSCP、OSCE³、著《資安這條路:領航新手的 Web Security 指南》。
教學經驗:60+ 企業教學經驗、指導過上百位學員。
教學特色:新手友善、耐心指導、擅長圖解(流程圖、心智圖)引導學習。
社群經驗:目前經營全臺資安社群 CURA,曾任臺科資安社社長、逢甲黑客社社長。
社群交流:LINE 社群《飛飛的資安大圈圈》,即時分享經驗、鼓勵交流。
社群分享:FB 粉專《資安這條路,飛飛來領路》,分享文章與圖卡整理。
個人網站:feifei.tw 分享資安技術文章;pbtw.tw 分享 AI 相關應用;ssdlc.feifei.tw 分享軟體安全開發流程文章。