2x02 - HIDL 与 AIDL (Treble 架构)
随着 Project Treble 的引入,Android 的 IPC 体系变得更加复杂,但也更加模块化。
这一章的研究目标不是记名词,而是回答三个问题:
- Framework 与 Vendor 的边界在哪里?
- HAL 进程/接口是如何被发现与约束的?
- 为什么“把东西搬出 system_server”会显著改变攻击面?
1. Project Treble 的初衷
在 Treble 之前,框架层(Framework)与硬件抽象层(HAL)紧密耦合。升级系统往往需要芯片厂商(如高通)配合更新 HAL。 Treble 通过将 Framework 与 HAL 分离,实现了“一次编写,到处运行”的系统升级。
更具体地说:
- 接口稳定性:Framework 通过稳定接口调用 Vendor 侧实现
- 可替换性:Vendor 不需要跟着 Framework 每次大改
- 安全隔离:让高风险解析/硬件交互跑在更合适的域里
2. HIDL (HAL Interface Definition Language)
HIDL 是专门为 HAL 设计的接口语言。
- Binderized 模式: HAL 运行在独立的进程中,通过
/dev/hwbinder与 Framework 通信。这是最安全、最推荐的模式。 - Passthrough 模式: 为了兼容旧版 HAL,允许 Framework 直接加载共享库(.so)。
安全意义
通过将 HAL 移出 system_server 进程,即使某个驱动程序(如相机、传感器)存在漏洞,攻击者也只能控制该 HAL 进程,而无法直接获取系统核心权限。
补充:Passthrough 模式的安全语义更差,因为它把 vendor 的 .so 直接拉进了 framework 进程空间,等价于扩大了高权限进程的攻击面(这也是 Treble 推 binderized 的原因之一)。
3. binder 与 hwbinder 的差异(理解边界)
binder:应用/系统服务广泛使用的通用 binderhwbinder:为 HAL 体系设计的 binder(历史上设备节点与服务发现体系不同)
从安全视角,关心的不是“哪个更高级”,而是:
- 哪些进程能访问对应的 binder 设备
- 服务运行在哪个 SELinux 域
- 接口是否稳定、是否容易被 fuzz
4. AIDL 的统一
在 Android 10 之后,AIDL 开始取代 HIDL 成为 HAL 的首选接口语言(称为 Stable AIDL)。
- 优势: 统一了应用层和系统层的开发体验。
- VNDK: 供应商原生开发套件,确保了库的版本兼容性。
Stable AIDL 的关键词:
- 接口版本化:明确兼容策略(新增方法、废弃方法)
- 跨分区稳定:system/vendor 边界上更可控
5. VINTF 与服务发现(研究入口)
在 Treble 体系下,“系统有哪些 HAL 服务、版本是多少、由谁提供”通常由清单机制描述(设备厂商与系统镜像共同决定)。
研究时常需要回答:
- 目标设备上是否存在某 HAL 服务
- 服务是 binderized 还是 passthrough
- 接口版本与实现位置
这些信息往往可以通过系统工具/清单侧线索定位(具体命令与文件在不同版本/厂商上差异较大)。
6. 攻击面分析
HAL 进程是系统中最接近硬件的用户态代码,也是内核漏洞利用的跳板和提权漏洞的热点。
6.1 常见漏洞模式
1. 共享内存越界
HAL 经常使用共享内存(ashmem/memfd)传递大量数据(如视频流、音频缓冲)。
// 典型的漏洞代码(Camera HAL)
void processCameraFrame(const native_handle_t* buffer, size_t size) {
void* data = mmap(buffer->data[0], size, ...); // size 来自 Framework
// 危险:未校验 size 是否与 buffer 实际大小匹配
memcpy(processingBuffer, data, size); // 越界读取
}攻击思路:
- Framework 传入一个小的 buffer 和一个大的 size
- HAL 越界读取 -> 信息泄露
- 或者 Framework 在 HAL 读取期间修改 buffer 内容(TOCTOU)
2. 接口参数契约不一致
// Framework 侧(Java)
cameraService.setParameters(width, height, format);
// width/height 单位:像素
// HAL 侧(C++)
void setParameters(uint32_t width, uint32_t height, uint32_t format) {
size_t bufferSize = width * height * getBytesPerPixel(format); // 整数溢出!
buffer = malloc(bufferSize);
}3. 句柄/FD 传递泄露
// 高权限 HAL 返回一个 camera FD 给应用
Return<void> getCameraFd(getCameraFd_cb _hidl_cb) {
int fd = open("/dev/video0", O_RDWR); // 敏感设备
_hidl_cb(fd); // 直接传给不可信调用方!
}攻击者可以直接操作该 FD,绕过 HAL 的访问控制。
4. 状态机与并发竞态
class MediaHal {
bool isConfigured = false;
void configure(const Config& config) {
// 配置硬件
isConfigured = true;
}
void processData(const Data& data) {
if (!isConfigured) return; // 竞态窗口
// 使用硬件处理数据
}
};多线程同时调用 configure 和 processData 可能导致状态不一致。
7. 研究与审计方法
7.1 从接口定义入手
Step 1: 定位接口文件
# 查找 HIDL 接口
find hardware/interfaces -name "*.hal"
# 查找 Stable AIDL 接口
find hardware/interfaces -name "*.aidl"
# 示例:Camera HAL
# hardware/interfaces/camera/device/3.2/ICameraDevice.halStep 2: 查看接口版本与方法
// ICameraDevice.hal
package android.hardware.camera.device@3.2;
interface ICameraDevice {
open(ICameraDeviceCallback callback) generates (Status status);
configureStreams(StreamConfiguration config)
generates (Status status, HalStreamConfiguration halConfig);
processCaptureRequest(CaptureRequest request)
generates (Status status);
// ... 其他方法
};Step 3: 找到实现进程与 SELinux 域
# 查看运行中的 HAL 进程
adb shell ps -A | grep "camera"
# 输出:system 1234 1 ... [email protected]
# 查看 SELinux 上下文
adb shell ps -Z | grep camera
# 输出:u:r:hal_camera_default:s0 ... [email protected]关键信息:
- 进程名:
[email protected] - SELinux 域:
hal_camera_default - UID 通常是
cameraserver或system
7.2 枚举可访问的 HAL 服务
# 列出所有 hwbinder 服务(需要 root)
adb shell lshal
# 输出示例:
# [email protected]::ICameraProvider/legacy/0
# Transport: hwbinder
# Server: [email protected]
# Clients: [cameraserver]关键字段:
Transport:hwbinder / passthroughServer:提供服务的进程Clients:当前连接的客户端(研究攻击路径)
7.3 Fuzzing HAL 接口
使用 VTS (Vendor Test Suite) 作为起点:
# VTS 包含了针对 HAL 接口的自动化测试
# 可以基于这些测试修改为 Fuzzer
# 示例:Camera HAL Fuzzer
adb shell /data/nativetest64/VtsHalCameraProviderV2_4TargetTest/VtsHalCameraProviderV2_4TargetTest自定义 Fuzzer(C++ 示例):
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
using android::hardware::camera::device::V3_2::ICameraDevice;
using android::sp;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// 获取 HAL 服务
sp<ICameraDevice> device = ICameraDevice::getService();
if (device == nullptr) return 0;
// 从 fuzzer 输入构造配置
StreamConfiguration config;
// ... 解析 data 到 config
// 调用目标接口
auto ret = device->configureStreams(config, [](auto status, auto halConfig) {
// 回调处理
});
return 0;
}编译与运行:
# 添加到 Android.bp
cc_fuzz {
name: "camera_hal_fuzzer",
srcs: ["camera_hal_fuzzer.cpp"],
shared_libs: [
"[email protected]",
"libhidlbase",
],
}
# 编译
m camera_hal_fuzzer
# 在设备上运行
adb push $OUT/data/fuzz/arm64/camera_hal_fuzzer /data/local/tmp/
adb shell /data/local/tmp/camera_hal_fuzzer7.4 动态追踪 HAL 调用
使用 Frida Hook HAL 接口:
// Hook Camera HAL 的 configureStreams 方法
function hookCameraHAL() {
// 加载 HAL 库
var cameraHal = Process.findModuleByName("[email protected]");
// Hook 特定函数(需要符号表或 offset)
var configureStreams = cameraHal.findExportByName("_ZN...configureStreamsE...");
Interceptor.attach(configureStreams, {
onEnter: function(args) {
console.log("[Camera HAL] configureStreams called");
console.log(" config pointer: " + args[1]);
// 解析 StreamConfiguration 结构
},
onLeave: function(retval) {
console.log(" returned: " + retval);
}
});
}
setImmediate(hookCameraHAL);使用 strace/systrace:
# 追踪 HAL 进程的系统调用
adb shell strace -p $(pidof [email protected]) -e trace=ioctl,mmap,open
# 追踪 hwbinder 通信
adb shell cat /sys/kernel/debug/binder/proc/$(pidof [email protected])7.5 识别高风险 HAL 服务(按优先级)
| HAL 类型 | 风险等级 | 原因 |
|---|---|---|
| Camera / Media | 🔴 极高 | 处理复杂编解码、大量共享内存、历史漏洞多 |
| Graphics / DRM | 🔴 极高 | GPU 交互、受保护内容、内核驱动交互 |
| Bluetooth / WiFi | 🟠 高 | 网络输入、协议栈复杂 |
| Sensors / GPS | 🟡 中 | 数据流持续、但通常格式简单 |
| Audio | 🟡 中 | 音频处理、可能涉及 DSP |
| Keymaster / Gatekeeper | 🟢 低-中 | 安全关键但接口简单、有硬件保护 |
选择策略:
- 优先选择暴露给第三方应用的 HAL(如 Camera)
- 关注处理外部数据的 HAL(如 Media Codec)
- 寻找厂商定制的 HAL(代码质量可能不如 AOSP)
参考(AOSP)
- 架构概览(含 HAL 层级、Treble 总体介绍入口):https://source.android.com/docs/core/architecture
- HIDL(Android 10 起废弃,官方迁移口径):https://source.android.com/docs/core/architecture/hidl
- AIDL 概览:https://source.android.com/docs/core/architecture/aidl
- 稳定的 AIDL(Stable AIDL):https://source.android.com/docs/core/architecture/aidl/stable-aidl