You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Android用户态获取Binder的binder_node有效句柄

Android 原生Binder服务注册与句柄获取(基于ioctl实现)

1. 打开Binder设备驱动

首先需要打开/dev/binder设备文件,建立与内核Binder驱动的通信通道:

int binder_fd = open("/dev/binder", O_RDWR);
if (binder_fd < 0) {
    perror("Failed to open /dev/binder");
    return -1;
}

2. 注册服务(创建binder_proc与binder_node)

通过发送BC_REGISTER_LOOPER和BC_ADD_SERVICE命令,完成进程的Binder looper注册与服务节点创建:

// 注册当前进程为Binder Looper,触发binder_proc创建
uint32_t register_cmd = BC_REGISTER_LOOPER;
struct binder_write_read bwr = {0};
bwr.write_size = sizeof(register_cmd);
bwr.write_buffer = (uintptr_t)&register_cmd;
bwr.read_size = 0;

if (ioctl(binder_fd, BINDER_WRITE_READ, &bwr) < 0) {
    perror("ioctl BC_REGISTER_LOOPER failed");
    close(binder_fd);
    return -1;
}

// 注册服务名称,触发binder_node创建
const char* service_name = "com.example.custombinder";
size_t name_len = strlen(service_name) + 1; // 包含字符串终止符

struct {
    uint32_t cmd;
    uint32_t handle; // 注册服务时填0
    uintptr_t name;
    uint32_t name_len;
    uint32_t flags; // 通常设为0
} __attribute__((packed)) add_service_data;

add_service_data.cmd = BC_ADD_SERVICE;
add_service_data.handle = 0;
add_service_data.name = (uintptr_t)service_name;
add_service_data.name_len = name_len;
add_service_data.flags = 0;

bwr.write_size = sizeof(add_service_data);
bwr.write_buffer = (uintptr_t)&add_service_data;
bwr.read_size = 0;

if (ioctl(binder_fd, BINDER_WRITE_READ, &bwr) < 0) {
    perror("ioctl BC_ADD_SERVICE failed");
    close(binder_fd);
    return -1;
}

3. 获取目标binder_node的有效句柄

场景1:获取其他进程已注册服务的句柄

通过BC_GET_SERVICE命令查询服务名称,内核会返回对应binder_node的句柄:

struct {
    uint32_t cmd;
    uintptr_t name;
    uint32_t name_len;
} __attribute__((packed)) get_service_data;

get_service_data.cmd = BC_GET_SERVICE;
get_service_data.name = (uintptr_t)service_name;
get_service_data.name_len = name_len;

bwr.write_size = sizeof(get_service_data);
bwr.write_buffer = (uintptr_t)&get_service_data;
bwr.read_size = sizeof(uint32_t); // 接收返回的句柄
uint32_t target_handle = 0;
bwr.read_buffer = (uintptr_t)&target_handle;

if (ioctl(binder_fd, BINDER_WRITE_READ, &bwr) < 0) {
    perror("ioctl BC_GET_SERVICE failed");
    close(binder_fd);
    return -1;
}

if (target_handle == 0) {
    fprintf(stderr, "Target service not found\n");
    close(binder_fd);
    return -1;
}

场景2:获取自身服务的句柄

若要向自身注册的服务发送事务,可直接使用0作为句柄(代表当前进程的Binder实体),或通过后续消息循环中接收的BR_TRANSACTION消息确认。

4. 完善事务发送代码(含Binder内存分配)

原生Binder事务数据需存放在驱动管理的共享内存中,需先通过BC_ALLOC_BUFFER分配内存,再执行你提供的BC_TRANSACTION逻辑:

// 分配Binder共享内存
uint32_t alloc_cmd = BC_ALLOC_BUFFER;
struct {
    uint32_t cmd;
    uint32_t size;
} __attribute__((packed)) alloc_data;
alloc_data.cmd = BC_ALLOC_BUFFER;
alloc_data.size = buffer_size + offsets_size; // 数据+偏移量总大小

bwr.write_size = sizeof(alloc_data);
bwr.write_buffer = (uintptr_t)&alloc_data;
bwr.read_size = sizeof(uintptr_t);
uintptr_t binder_shared_buf = 0;
bwr.read_buffer = (uintptr_t)&binder_shared_buf;

if (ioctl(binder_fd, BINDER_WRITE_READ, &bwr) < 0) {
    perror("ioctl BC_ALLOC_BUFFER failed");
    close(binder_fd);
    return -1;
}

// 将用户空间数据拷贝到共享内存
memcpy((void*)binder_shared_buf, data_buffer, buffer_size);
memcpy((void*)(binder_shared_buf + buffer_size), off_buffer, offsets_size);

// 构造事务数据
struct binder_transaction_data tr = {0};
tr.target.handle = target_handle; // 替换为获取到的有效句柄
tr.code = 0;
tr.data_size = buffer_size;
tr.offsets_size = offsets_size;
tr.data.ptr.buffer = binder_shared_buf;
tr.data.ptr.offsets = binder_shared_buf + buffer_size;

// 发送BC_TRANSACTION
struct {
    uint32_t cmd;
    struct binder_transaction_data tr;
} __attribute__((packed)) write_data;

write_data.cmd = BC_TRANSACTION;
write_data.tr = tr;

bwr.write_size = sizeof(write_data);
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t)&write_data;
bwr.read_size = 0;

if (ioctl(binder_fd, BINDER_WRITE_READ, &bwr) < 0) {
    perror("[-] ioctl BINDER_WRITE_READ failed");
}

// 释放共享内存(可选,若后续不再使用)
uint32_t free_cmd = BC_FREE_BUFFER;
struct {
    uint32_t cmd;
    uintptr_t buffer;
} __attribute__((packed)) free_data;
free_data.cmd = BC_FREE_BUFFER;
free_data.buffer = binder_shared_buf;

bwr.write_size = sizeof(free_data);
bwr.write_buffer = (uintptr_t)&free_data;
bwr.read_size = 0;
ioctl(binder_fd, BINDER_WRITE_READ, &bwr);

关键注意事项

  • 消息循环:注册服务后需持续调用ioctl读取驱动返回的BR_XXX命令(如BR_TRANSACTION、BR_REPLY),否则驱动会判定进程无响应
  • 权限:访问/dev/binder需要系统权限或特定应用权限,普通第三方应用无法直接操作
  • 内存安全:必须通过BC_ALLOC_BUFFER/BC_FREE_BUFFER管理Binder共享内存,避免内存泄漏

内容的提问来源于stack exchange,提问作者Cyb3rCr0wCC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 21:17:25