├── LICENSE ├── README.md ├── jni ├── Android.mk ├── Application.mk ├── binder_util.c ├── elf_util.c ├── entry.c ├── hook_util.c └── include │ ├── binder.h │ ├── binder_util.h │ ├── elf_util.h │ ├── hook_util.h │ └── log.h ├── libs └── arm64-v8a │ └── libbinderhook.so └── obj └── local ├── arm64-v8a ├── libbinderhook.so └── objs │ └── binderhook │ ├── binder_util.o │ ├── binder_util.o.d │ ├── elf_util.o │ ├── elf_util.o.d │ ├── entry.o │ ├── entry.o.d │ ├── hook_util.o │ └── hook_util.o.d └── armeabi-v7a ├── libbinderhook.so └── objs └── binderhook ├── binder_util.o ├── binder_util.o.d ├── elf_util.o ├── elf_util.o.d ├── entry.o ├── entry.o.d ├── hook_util.o └── hook_util.o.d /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 EggUncle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hermes 2 | 3 | A tool to dump BR&BC_TRANSACTION BR&BC_REPLY data of binder ,like this: 4 | 5 | ![img](https://github.com/EggUncle/Demo/blob/master/markdownimg/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202018-12-11%20%E4%B8%8A%E5%8D%8812.23.24.png?raw=true) 6 | 7 | ### How to use it 8 | build a so ,then inject it to process of com.andriod.phone or system_server ,call entry function 'hook_entry'. 9 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog 6 | LOCAL_MODULE := binderhook 7 | LOCAL_SRC_FILES := hook_util.c 8 | LOCAL_SRC_FILES += binder_util.c 9 | LOCAL_SRC_FILES += elf_util.c 10 | LOCAL_SRC_FILES += entry.c 11 | 12 | LOCAL_C_INCLUDES += $(PROJECT_PATH)../include 13 | 14 | include $(BUILD_SHARED_LIBRARY) 15 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := arm64-v8a #armeabi-v7a 2 | -------------------------------------------------------------------------------- /jni/binder_util.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | 5 | 6 | #include 7 | #include "include/binder.h" 8 | #include "include/binder_util.h" 9 | #include 10 | #include "include/log.h" 11 | #include 12 | 13 | #define DUMP_ALL 1 14 | #define ONLY_CHAR 0 15 | #define PLACE_HOLDER " " 16 | 17 | struct hex_data { 18 | char *hex; 19 | char *str; 20 | }; 21 | 22 | static void hex_data_init(struct hex_data *data, int length) { 23 | data->hex = calloc(1, 2 * length * sizeof(char) + 1); 24 | data->str = calloc(1, length * sizeof(char) + 1); 25 | } 26 | 27 | static void hex_data_clean(struct hex_data *data) { 28 | free(data->hex); 29 | free(data->str); 30 | } 31 | 32 | static int hexdump(binder_uintptr_t binder_data, binder_size_t len, struct hex_data *h_data, 33 | int dump_all) { 34 | char *data = (char *) binder_data; 35 | char tmp_str[1]; 36 | char tmp_hex[2]; 37 | int index = 0; 38 | for (int count = 0; count < len; count++) { 39 | int ascii = *data; 40 | sprintf(tmp_hex, "%02x", ascii); 41 | memcpy(h_data->hex + count * 2, tmp_hex, 2); 42 | if ((*data >= 33) && (*data <= 122)) { 43 | sprintf(tmp_str, "%c", *data); 44 | memcpy(h_data->str + index, tmp_str, 1); 45 | index++; 46 | } else if (dump_all == DUMP_ALL) { 47 | memcpy(h_data->str + index, ".", 1); 48 | index++; 49 | } 50 | data++; 51 | } 52 | memcpy(h_data->hex + len * 2 + 1, "\0", 1); 53 | memcpy(h_data->str + index + 1, "\0", 1); 54 | } 55 | 56 | int parse_binder_data(struct binder_transaction_data *transaction_data) { 57 | binder_uintptr_t _data = transaction_data->data.ptr.buffer; 58 | binder_size_t len = transaction_data->data_size; 59 | struct hex_data h_data[1]; 60 | hex_data_init(h_data, len); 61 | hexdump(_data, len, h_data, ONLY_CHAR); 62 | LOGE("PID = %d, code = %d, dump name : %s , pname size is %d, data size is %lld , target is %llx %llx offset is %lx\n", 63 | transaction_data->sender_pid, transaction_data->code, h_data->str, strlen(h_data->str), 64 | transaction_data->data_size, &transaction_data->target.handle, 65 | &transaction_data->target.ptr, transaction_data->data_offsets); 66 | hex_data_clean(h_data); 67 | hex_data_init(h_data, len); 68 | hexdump(_data, len, h_data, DUMP_ALL); 69 | int i = 0; 70 | char *tmp_str = calloc(1, sizeof(char) * 16 + 1); 71 | char *tmp_hex = calloc(1, sizeof(char) * 8 + 1); 72 | char *tmp_hex_2 = calloc(1, sizeof(char) * 8 + 1); 73 | char *tmp_hex_3 = calloc(1, sizeof(char) * 8 + 1); 74 | char *tmp_hex_4 = calloc(1, sizeof(char) * 8 + 1); 75 | int str_start_index = 0; 76 | do { 77 | str_start_index = 4; 78 | memcpy(tmp_hex, h_data->hex + i * 2, 8); 79 | memcpy(tmp_hex + 8, "\0", 1); 80 | if (i * 2 + 16 <= len * 2) { 81 | str_start_index = 8; 82 | memcpy(tmp_hex_2, h_data->hex + i * 2 + 8, 8); 83 | memcpy(tmp_hex_2 + 8, "\0", 1); 84 | } else { 85 | memcpy(tmp_hex_2, PLACE_HOLDER, 8); 86 | memcpy(tmp_hex_2 + 8, "\0", 1); 87 | } 88 | if (i * 2 + 24 <= len * 2) { 89 | str_start_index = 12; 90 | memcpy(tmp_hex_3, h_data->hex + i * 2 + 16, 8); 91 | memcpy(tmp_hex_3 + 8, "\0", 1); 92 | } else { 93 | memcpy(tmp_hex_3, PLACE_HOLDER, 8); 94 | memcpy(tmp_hex_3 + 8, "\0", 1); 95 | } 96 | if (i * 2 + 32 <= len * 2) { 97 | str_start_index = 16; 98 | memcpy(tmp_hex_4, h_data->hex + i * 2 + 24, 8); 99 | memcpy(tmp_hex_4 + 8, "\0", 1); 100 | } else { 101 | memcpy(tmp_hex_4, PLACE_HOLDER, 8); 102 | memcpy(tmp_hex_4 + 8, "\0", 1); 103 | } 104 | memcpy(tmp_str, h_data->str + i, str_start_index); 105 | memcpy(tmp_str + str_start_index, "\0", 1); 106 | LOGD("%s %8s %8s %8s %s", tmp_hex, tmp_hex_2, tmp_hex_3, tmp_hex_4, tmp_str); 107 | i += 16; 108 | } while (i < len); 109 | free(tmp_hex); 110 | free(tmp_hex_2); 111 | free(tmp_hex_3); 112 | free(tmp_hex_4); 113 | free(tmp_str); 114 | return 0; 115 | } -------------------------------------------------------------------------------- /jni/elf_util.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "include/log.h" 12 | #include "include/elf_util.h" 13 | 14 | FILE *open_elf(char *path) { 15 | if (path != NULL) { 16 | LOGD("open lib %s\n", path); 17 | FILE *fp = fopen(path, "rb"); 18 | if (fp == NULL) { 19 | LOGD("opendir: %s\n", strerror(errno)); 20 | } 21 | return fp; 22 | } 23 | return NULL; 24 | } 25 | 26 | void close_elf(FILE *file) { 27 | if (file != NULL) { 28 | printf("Close ELF file\n"); 29 | fclose(file); 30 | } 31 | } 32 | 33 | void parse_elf_header(Elf_Ehdr *elf_header, FILE *elf_file) { 34 | if (elf_header == NULL || elf_file == NULL) { 35 | LOGD("elf_header is null or elf_file is null"); 36 | return; 37 | } 38 | fseek(elf_file, 0, SEEK_SET); 39 | fread(elf_header, sizeof(Elf_Ehdr), 1, elf_file); 40 | } 41 | 42 | char *parse_shstrtab_content(FILE *elf_file, Elf_Ehdr *elf_header) { 43 | off_t shstrtab_header_offset = 44 | elf_header->e_shoff + elf_header->e_shstrndx * sizeof(Elf_Ehdr); 45 | Elf_Shdr *shstrtab_header = (Elf_Shdr *) malloc(sizeof(Elf_Shdr)); 46 | fseek(elf_file, shstrtab_header_offset, SEEK_SET); 47 | fread(shstrtab_header, sizeof(Elf_Shdr), 1, elf_file); 48 | Elf_Xword sh_size = shstrtab_header->sh_size; 49 | char *shstrtab_content = (char *) malloc(sh_size * sizeof(char)); 50 | off_t shstrtab_base_offset = shstrtab_header->sh_offset; 51 | fseek(elf_file, shstrtab_base_offset, SEEK_SET); 52 | fread(shstrtab_content, sh_size, 1, elf_file); 53 | return shstrtab_content; 54 | } 55 | 56 | Elf_Shdr *parse_target_table_data(char *shstrtab_content, FILE *elf_file, Elf_Ehdr *elf_header, 57 | char *target_tab_name) { 58 | off_t base_offset = elf_header->e_shoff; 59 | Elf_Half e_shnum = elf_header->e_shnum; 60 | Elf_Shdr *tmp_header = (Elf_Shdr *) malloc(sizeof(Elf_Shdr)); 61 | for (int i = 0; i < e_shnum; ++i) { 62 | fseek(elf_file, base_offset, SEEK_SET); 63 | fread(tmp_header, sizeof(Elf_Shdr), 1, elf_file); 64 | char *section_name = shstrtab_content + tmp_header->sh_name; 65 | if (strcmp(section_name, target_tab_name) == 0) { 66 | // LOGD("%s\n", section_name); 67 | break; 68 | } 69 | base_offset += sizeof(Elf_Shdr); 70 | } 71 | return tmp_header; 72 | } 73 | 74 | long get_libs_addr(pid_t pid, char *lib_name) { 75 | char mapsPath[32]; 76 | long addr = 0; 77 | if (pid < 0) { 78 | sprintf(mapsPath, "/proc/self/maps"); 79 | } else { 80 | sprintf(mapsPath, "/proc/%d/maps", pid); 81 | } 82 | FILE *maps = fopen(mapsPath, "r"); 83 | char str_line[1024]; 84 | // printf("%s", mapsPath); 85 | while (!feof(maps)) { 86 | fgets(str_line, 1024, maps); 87 | if (strstr(str_line, lib_name) != NULL) { 88 | fclose(maps); 89 | addr = strtoul(strtok(str_line, "-"), NULL, 16); 90 | //LOGI("%lx\n", addr); 91 | if (addr == 0x8000) 92 | addr = 0; 93 | break; 94 | } 95 | } 96 | fclose(maps); 97 | return addr; 98 | } 99 | 100 | long get_segment_base_address(int fd, long base_addr, int phnum, size_t phsize, 101 | unsigned long phdr_addr) { 102 | if (phnum > 0) { 103 | Elf_Phdr phdr; 104 | lseek(fd, phdr_addr, SEEK_SET);//将指针移至程序头表偏移地址 105 | for (Elf_Half i = 0; i < phnum; i++) { 106 | read(fd, &phdr, phsize); 107 | if (phdr.p_type == PT_LOAD) 108 | break; 109 | } 110 | return base_addr + phdr.p_offset - phdr.p_vaddr; 111 | } 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /jni/entry.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | 5 | 6 | #include "include/hook_util.h" 7 | 8 | void hook_entry() { 9 | got_hook_ioctl(); 10 | } -------------------------------------------------------------------------------- /jni/hook_util.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "include/binder.h" 12 | #include "include/binder_util.h" 13 | #include "include/elf_util.h" 14 | #include "include/log.h" 15 | 16 | int (*old_ioctl)(int __fd, unsigned long int __request, void *arg); 17 | 18 | int new_ioctl(int __fd, unsigned long int __request, void *arg) { 19 | //./data/local/tmp/ptraceMain system_server hook_entry /data/local/tmp/libbinderhook.so 20 | //./data/local/tmp/ptraceMain com.android.phone hook_entry /data/local/tmp/libbinderhook-lib.so 21 | //./data/local/tmp/ptraceMain com.test.gothooktest hook_entry /data/local/tmp/libbinderhook.so 22 | if (__request == BINDER_WRITE_READ) { 23 | struct binder_write_read *tmp = (struct binder_write_read *) arg; 24 | binder_size_t read_size = tmp->read_size; 25 | binder_size_t write_size = tmp->write_size; 26 | LOGE("---------------------------------\n"); 27 | if (read_size > 0) { 28 | binder_size_t already_got_size = tmp->read_consumed; 29 | void *pret = 0; 30 | while (already_got_size < read_size) {//循环处理read_buffer中的每一个命令 31 | pret = (uint32_t * )(tmp->read_buffer + already_got_size); 32 | uint32_t cmd = *(uint32_t *) pret;//获得命令码 33 | pret += sizeof(uint32_t); 34 | binder_size_t size = _IOC_SIZE(cmd); //从命令参数中解析出用户数据大小 35 | struct binder_transaction_data *pdata = (struct binder_transaction_data *) pret; 36 | 37 | switch (cmd) { 38 | case BR_TRANSACTION: { 39 | LOGE("read BR_TRANSACTION"); 40 | parse_binder_data(pdata); 41 | } 42 | break; 43 | case BR_REPLY: { 44 | LOGE("read BR_REPLY"); 45 | parse_binder_data(pdata); 46 | } 47 | break; 48 | case BR_TRANSACTION_COMPLETE: { 49 | LOGE("read BR_TRANSACTION_COMPLETE"); 50 | parse_binder_data(pdata); 51 | } 52 | break; 53 | default: 54 | break; 55 | } 56 | already_got_size += size + 4;//数据内容加上命令码 57 | } 58 | } 59 | if (write_size > 0) { 60 | binder_size_t already_got_size = tmp->write_consumed; 61 | void *pret = 0; 62 | while (already_got_size < write_size) {//循环处理write_buffer中的每一个命令 63 | pret = (uint32_t * )(tmp->write_buffer + already_got_size); 64 | uint32_t cmd = *(uint32_t *) pret;//获得命令码 65 | pret += sizeof(uint32_t); 66 | binder_size_t size = _IOC_SIZE(cmd); //从命令参数中解析出用户数据大小 67 | struct binder_transaction_data *pdata = (struct binder_transaction_data *) pret; 68 | 69 | switch (cmd) { 70 | case BC_TRANSACTION: { 71 | LOGE("write BC_TRANSACTION"); 72 | parse_binder_data(pdata); 73 | } 74 | break; 75 | case BC_REPLY: { 76 | LOGE("write BC_REPLY"); 77 | parse_binder_data(pdata); 78 | } 79 | break; 80 | default: 81 | break; 82 | } 83 | already_got_size += size + 4;//数据内容加上命令码 84 | } 85 | } 86 | } 87 | 88 | return old_ioctl(__fd, __request, arg); 89 | } 90 | 91 | int got_hook(char *path, char *target_func_name, int *old_func, void *new_func) { 92 | 93 | FILE *elf_file = open_elf(path); 94 | if (elf_file == NULL) { 95 | LOGD("elf file is null \n"); 96 | return 0; 97 | } 98 | Elf_Ehdr *elf_header = (Elf_Ehdr *) malloc(sizeof(Elf_Ehdr)); 99 | parse_elf_header(elf_header, elf_file); 100 | if (elf_header == NULL) { 101 | LOGD("elf_head is null \n"); 102 | return 0; 103 | } 104 | 105 | int fd = open(path, O_RDONLY); 106 | long target_lib_base_addr = get_libs_addr(-1, path); 107 | LOGD("target base addr is %lx\n", target_lib_base_addr); 108 | //基址不一定是maps中的地址,当第一个PT_LOAD 的vaddr不为0的时候,需要进行额外的计算 109 | unsigned long phdr_addr = elf_header->e_phoff;//程序头表在文件中的偏移量 110 | int phnum = elf_header->e_phnum;//程序头表表项数目 111 | size_t phsize = elf_header->e_phentsize;//程序头表项的大小 112 | long bias = get_segment_base_address(fd, target_lib_base_addr, phnum, phsize, 113 | phdr_addr);//获得该段的内存基址 114 | LOGD("target segment base address is %lx\n", bias); 115 | //read shstrtab content 116 | char *shstrtab_content = parse_shstrtab_content(elf_file, elf_header); 117 | Elf_Shdr *dynsym_header = parse_target_table_data(shstrtab_content, elf_file, elf_header, 118 | ".dynsym"); 119 | Elf_Shdr *dynstr_header = parse_target_table_data(shstrtab_content, elf_file, elf_header, 120 | ".dynstr"); 121 | //read dynstr data 122 | char *dynstr = (char *) malloc(sizeof(char) * dynstr_header->sh_size); 123 | fseek(elf_file, dynstr_header->sh_offset, SEEK_SET); 124 | fread(dynstr, dynstr_header->sh_size, 1, elf_file); 125 | 126 | Elf_Sym *dynsymtab = (Elf_Sym *) malloc(dynsym_header->sh_size); 127 | fseek(elf_file, dynsym_header->sh_offset, SEEK_SET); 128 | fread(dynsymtab, dynsym_header->sh_size, 1, elf_file); 129 | 130 | long result_offset = 0; 131 | //search target in rela.plt 132 | Elf_Shdr *rela_plt_header = parse_target_table_data(shstrtab_content, elf_file, elf_header, 133 | ".rela.plt"); 134 | Elf64_Rela *rela_plt_tab = malloc(rela_plt_header->sh_size); 135 | 136 | fseek(elf_file, rela_plt_header->sh_offset, SEEK_SET); 137 | fread(rela_plt_tab, rela_plt_header->sh_size, 1, elf_file); 138 | LOGD("rela_plt size %llx\n", 139 | rela_plt_header->sh_size / rela_plt_header->sh_entsize); 140 | LOGD("rela_plt en size %ld sizeof elf rel %ld\n", rela_plt_header->sh_entsize, 141 | sizeof(Elf64_Rel)); 142 | int success = 0; 143 | 144 | LOGD("ioctl addr is %lx\n", ioctl); 145 | LOGD("dynstr sh_size : %llx \n sh_entsize : %llx \n offset : %llx\n", 146 | dynstr_header->sh_size, dynstr_header->sh_entsize, dynstr_header->sh_offset); 147 | for (int i = 0; i < rela_plt_header->sh_size / rela_plt_header->sh_entsize; ++i) { 148 | Elf64_Rela *rel_ent = rela_plt_tab + i; 149 | unsigned ndx = ELF_R_SYM(rel_ent->r_info); 150 | char *syn = dynstr + dynsymtab[ndx].st_name; 151 | //LOGD("%d %s %lx\n", ndx, syn, rel_ent->r_offset); 152 | if (strcmp(target_func_name, syn) == 0) { 153 | //LOGD("ndx = %d, str = %s i = %d \n", ndx, dynstr + dynsymtab[ndx].st_name, i); 154 | result_offset = rela_plt_tab[i].r_offset; 155 | uint64_t target_func_addr = (uint64_t)(result_offset + bias); 156 | if (*(long *) target_func_addr == old_func) { 157 | //备份原来的ioctl 158 | old_ioctl = old_func; 159 | long *point = (long *) target_func_addr; 160 | mprotect((void *) PAGE_START(target_func_addr), PAGE_SIZE, 161 | PROT_READ | PROT_WRITE); 162 | *point = new_func; 163 | //clear cache of code 164 | __builtin___clear_cache((char *) PAGE_START(target_func_addr), 165 | (char *) PAGE_END(target_func_addr)); 166 | success = 1; 167 | } 168 | break; 169 | } 170 | } 171 | 172 | if (success) { 173 | LOGD("hook success\n"); 174 | } else { 175 | LOGD("hook failed\n"); 176 | } 177 | close_elf(elf_file); 178 | } 179 | 180 | int got_hook_ioctl() { 181 | #if defined(__arm__) 182 | char *lib_binder_path = "/system/lib/libbinder.so"; 183 | #else 184 | char *lib_binder_path = "/system/lib64/libbinder.so"; 185 | #endif 186 | char *target_function_name = "ioctl"; 187 | got_hook(lib_binder_path, target_function_name, ioctl, new_ioctl); 188 | } 189 | 190 | -------------------------------------------------------------------------------- /jni/include/binder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 Google, Inc. 3 | * 4 | * Based on, but no longer compatible with, the original 5 | * OpenBinder.org binder driver interface, which is: 6 | * 7 | * Copyright (c) 2005 Palmsource, Inc. 8 | * 9 | * This software is licensed under the terms of the GNU General Public 10 | * License version 2, as published by the Free Software Foundation, and 11 | * may be copied, distributed, and modified under those terms. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | */ 19 | 20 | #ifndef _UAPI_LINUX_BINDER_H 21 | #define _UAPI_LINUX_BINDER_H 22 | 23 | #include 24 | 25 | #define B_PACK_CHARS(c1, c2, c3, c4) \ 26 | ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) 27 | #define B_TYPE_LARGE 0x85 28 | 29 | enum { 30 | BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), 31 | BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), 32 | BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), 33 | BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), 34 | BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), 35 | }; 36 | 37 | enum { 38 | FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, 39 | FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, 40 | }; 41 | 42 | #ifdef BINDER_IPC_32BIT 43 | typedef __u32 binder_size_t; 44 | typedef __u32 binder_uintptr_t; 45 | #else 46 | typedef __u64 binder_size_t; 47 | typedef __u64 binder_uintptr_t; 48 | #endif 49 | 50 | /* 51 | * This is the flattened representation of a Binder object for transfer 52 | * between processes. The 'offsets' supplied as part of a binder transaction 53 | * contains offsets into the data where these structures occur. The Binder 54 | * driver takes care of re-writing the structure type and data as it moves 55 | * between processes. 56 | */ 57 | struct flat_binder_object { 58 | /* 8 bytes for large_flat_header. */ 59 | __u32 type; 60 | __u32 flags; 61 | 62 | /* 8 bytes of data. */ 63 | union { 64 | binder_uintptr_t binder; /* local object */ 65 | __u32 handle; /* remote object */ 66 | }; 67 | 68 | /* extra data associated with local object */ 69 | binder_uintptr_t cookie; 70 | }; 71 | 72 | /* 73 | * On 64-bit platforms where user code may run in 32-bits the driver must 74 | * translate the buffer (and local binder) addresses appropriately. 75 | */ 76 | 77 | struct binder_write_read { 78 | binder_size_t write_size; /* bytes to write */ 79 | binder_size_t write_consumed; /* bytes consumed by driver */ 80 | binder_uintptr_t write_buffer; 81 | binder_size_t read_size; /* bytes to read */ 82 | binder_size_t read_consumed; /* bytes consumed by driver */ 83 | binder_uintptr_t read_buffer; 84 | }; 85 | 86 | /* Use with BINDER_VERSION, driver fills in fields. */ 87 | struct binder_version { 88 | /* driver protocol version -- increment with incompatible change */ 89 | __s32 protocol_version; 90 | }; 91 | 92 | /* This is the current protocol version. */ 93 | #ifdef BINDER_IPC_32BIT 94 | #define BINDER_CURRENT_PROTOCOL_VERSION 7 95 | #else 96 | #define BINDER_CURRENT_PROTOCOL_VERSION 8 97 | #endif 98 | 99 | #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) 100 | #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) 101 | #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) 102 | #define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) 103 | #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) 104 | #define BINDER_THREAD_EXIT _IOW('b', 8, __s32) 105 | #define BINDER_VERSION _IOWR('b', 9, struct binder_version) 106 | 107 | /* 108 | * NOTE: Two special error codes you should check for when calling 109 | * in to the driver are: 110 | * 111 | * EINTR -- The operation has been interupted. This should be 112 | * handled by retrying the ioctl() until a different error code 113 | * is returned. 114 | * 115 | * ECONNREFUSED -- The driver is no longer accepting operations 116 | * from your process. That is, the process is being destroyed. 117 | * You should handle this by exiting from your process. Note 118 | * that once this error code is returned, all further calls to 119 | * the driver from any thread will return this same code. 120 | */ 121 | 122 | enum transaction_flags { 123 | TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */ 124 | TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */ 125 | TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */ 126 | TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */ 127 | }; 128 | 129 | struct binder_transaction_data { 130 | /* The first two are only used for bcTRANSACTION and brTRANSACTION, 131 | * identifying the target and contents of the transaction. 132 | */ 133 | union { 134 | /* target descriptor of command transaction */ 135 | __u32 handle; 136 | /* target descriptor of return transaction */ 137 | binder_uintptr_t ptr; 138 | } target; 139 | binder_uintptr_t cookie; /* target object cookie */ 140 | __u32 code; /* transaction command */ 141 | 142 | /* General information about the transaction. */ 143 | __u32 flags; 144 | pid_t sender_pid; 145 | uid_t sender_euid; 146 | binder_size_t data_size; /* number of bytes of data */ 147 | binder_size_t data_offsets; /* number of bytes of offsets */ 148 | 149 | /* If this transaction is inline, the data immediately 150 | * follows here; otherwise, it ends with a pointer to 151 | * the data buffer. 152 | */ 153 | union { 154 | struct { 155 | /* transaction data */ 156 | binder_uintptr_t buffer; 157 | /* offsets from buffer to flat_binder_object structs */ 158 | binder_uintptr_t offsets; 159 | } ptr; 160 | __u8 buf[8]; 161 | } data; 162 | }; 163 | 164 | struct binder_ptr_cookie { 165 | binder_uintptr_t ptr; 166 | binder_uintptr_t cookie; 167 | }; 168 | 169 | struct binder_handle_cookie { 170 | __u32 handle; 171 | binder_uintptr_t cookie; 172 | } __packed; 173 | 174 | struct binder_pri_desc { 175 | __s32 priority; 176 | __u32 desc; 177 | }; 178 | 179 | struct binder_pri_ptr_cookie { 180 | __s32 priority; 181 | binder_uintptr_t ptr; 182 | binder_uintptr_t cookie; 183 | }; 184 | 185 | enum binder_driver_return_protocol { 186 | BR_ERROR = _IOR('r', 0, __s32), 187 | /* 188 | * int: error code 189 | */ 190 | 191 | BR_OK = _IO('r', 1), 192 | /* No parameters! */ 193 | 194 | BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), 195 | BR_REPLY = _IOR('r', 3, struct binder_transaction_data), 196 | /* 197 | * binder_transaction_data: the received command. 198 | */ 199 | 200 | BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), 201 | /* 202 | * not currently supported 203 | * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. 204 | * Else the remote object has acquired a primary reference. 205 | */ 206 | 207 | BR_DEAD_REPLY = _IO('r', 5), 208 | /* 209 | * The target of the last transaction (either a bcTRANSACTION or 210 | * a bcATTEMPT_ACQUIRE) is no longer with us. No parameters. 211 | */ 212 | 213 | BR_TRANSACTION_COMPLETE = _IO('r', 6), 214 | /* 215 | * No parameters... always refers to the last transaction requested 216 | * (including replies). Note that this will be sent even for 217 | * asynchronous transactions. 218 | */ 219 | 220 | BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), 221 | BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), 222 | BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), 223 | BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), 224 | /* 225 | * void *: ptr to binder 226 | * void *: cookie for binder 227 | */ 228 | 229 | BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), 230 | /* 231 | * not currently supported 232 | * int: priority 233 | * void *: ptr to binder 234 | * void *: cookie for binder 235 | */ 236 | 237 | BR_NOOP = _IO('r', 12), 238 | /* 239 | * No parameters. Do nothing and examine the next command. It exists 240 | * primarily so that we can replace it with a BR_SPAWN_LOOPER command. 241 | */ 242 | 243 | BR_SPAWN_LOOPER = _IO('r', 13), 244 | /* 245 | * No parameters. The driver has determined that a process has no 246 | * threads waiting to service incoming transactions. When a process 247 | * receives this command, it must spawn a new service thread and 248 | * register it via bcENTER_LOOPER. 249 | */ 250 | 251 | BR_FINISHED = _IO('r', 14), 252 | /* 253 | * not currently supported 254 | * stop threadpool thread 255 | */ 256 | 257 | BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), 258 | /* 259 | * void *: cookie 260 | */ 261 | BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), 262 | /* 263 | * void *: cookie 264 | */ 265 | 266 | BR_FAILED_REPLY = _IO('r', 17), 267 | /* 268 | * The the last transaction (either a bcTRANSACTION or 269 | * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters. 270 | */ 271 | }; 272 | 273 | enum binder_driver_command_protocol { 274 | BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), 275 | BC_REPLY = _IOW('c', 1, struct binder_transaction_data), 276 | /* 277 | * binder_transaction_data: the sent command. 278 | */ 279 | 280 | BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), 281 | /* 282 | * not currently supported 283 | * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. 284 | * Else you have acquired a primary reference on the object. 285 | */ 286 | 287 | BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), 288 | /* 289 | * void *: ptr to transaction data received on a read 290 | */ 291 | 292 | BC_INCREFS = _IOW('c', 4, __u32), 293 | BC_ACQUIRE = _IOW('c', 5, __u32), 294 | BC_RELEASE = _IOW('c', 6, __u32), 295 | BC_DECREFS = _IOW('c', 7, __u32), 296 | /* 297 | * int: descriptor 298 | */ 299 | 300 | BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), 301 | BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), 302 | /* 303 | * void *: ptr to binder 304 | * void *: cookie for binder 305 | */ 306 | 307 | BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), 308 | /* 309 | * not currently supported 310 | * int: priority 311 | * int: descriptor 312 | */ 313 | 314 | BC_REGISTER_LOOPER = _IO('c', 11), 315 | /* 316 | * No parameters. 317 | * Register a spawned looper thread with the device. 318 | */ 319 | 320 | BC_ENTER_LOOPER = _IO('c', 12), 321 | BC_EXIT_LOOPER = _IO('c', 13), 322 | /* 323 | * No parameters. 324 | * These two commands are sent as an application-level thread 325 | * enters and exits the binder loop, respectively. They are 326 | * used so the binder can have an accurate count of the number 327 | * of looping threads it has available. 328 | */ 329 | 330 | BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, 331 | struct binder_handle_cookie), 332 | /* 333 | * int: handle 334 | * void *: cookie 335 | */ 336 | 337 | BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, 338 | struct binder_handle_cookie), 339 | /* 340 | * int: handle 341 | * void *: cookie 342 | */ 343 | 344 | BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), 345 | /* 346 | * void *: cookie 347 | */ 348 | }; 349 | 350 | #endif /* _UAPI_LINUX_BINDER_H */ 351 | 352 | -------------------------------------------------------------------------------- /jni/include/binder_util.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | #pragma once 5 | 6 | int parse_binder_data(struct binder_transaction_data *transaction_data); -------------------------------------------------------------------------------- /jni/include/elf_util.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #if defined(__arm__) 5 | #define Elf_Ehdr Elf32_Ehdr 6 | #define Elf_Shdr Elf32_Shdr 7 | #define Elf_Phdr Elf32_Phdr 8 | #define Elf_Sym Elf32_Sym 9 | #define Elf_Rel Elf32_Rel 10 | #define Elf_Xword Elf32_Word 11 | #define Elf_Half Elf32_Half 12 | #define Elf_Off Elf32_Off 13 | #define ELF_R_SYM ELF32_R_SYM 14 | #else 15 | #define Elf_Ehdr Elf64_Ehdr 16 | #define Elf_Shdr Elf64_Shdr 17 | #define Elf_Phdr Elf64_Phdr 18 | #define Elf_Sym Elf64_Sym 19 | #define Elf_Rel Elf64_Rel 20 | #define Elf_Xword Elf64_Xword 21 | #define Elf_Half Elf64_Half 22 | #define Elf_Off Elf64_Off 23 | #define ELF_R_SYM ELF64_R_SYM 24 | #endif 25 | 26 | #define PAGE_START(addr) ((addr) & PAGE_MASK) 27 | #define PAGE_END(addr) (PAGE_START(addr) + PAGE_SIZE) 28 | 29 | 30 | FILE *open_elf(char *path); 31 | 32 | void close_elf(FILE *file); 33 | 34 | void parse_elf_header(Elf_Ehdr *elf_header, FILE *elf_file); 35 | 36 | char *parse_shstrtab_content(FILE *elf_file, Elf_Ehdr *elf_header); 37 | 38 | Elf_Shdr *parse_target_table_data(char *shstrtab_content, FILE *elf_file, Elf_Ehdr *elf_header, 39 | char *target_tab_name); 40 | 41 | long get_segment_base_address(int fd, long base_addr, int phnum, size_t phsize, 42 | unsigned long phdr_addr); 43 | 44 | long get_libs_addr(pid_t pid, char *lib_name); 45 | -------------------------------------------------------------------------------- /jni/include/hook_util.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | #pragma once 5 | 6 | int got_hook_ioctl(); -------------------------------------------------------------------------------- /jni/include/log.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by egguncle on 2019/4/12. 3 | // 4 | #pragma once 5 | 6 | #include 7 | 8 | #define TAG "LIB_BINDER_HOOK" // 这个是自定义的LOG的标识 9 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 10 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 11 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 12 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 13 | #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型 14 | -------------------------------------------------------------------------------- /libs/arm64-v8a/libbinderhook.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/libs/arm64-v8a/libbinderhook.so -------------------------------------------------------------------------------- /obj/local/arm64-v8a/libbinderhook.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/arm64-v8a/libbinderhook.so -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/binder_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/arm64-v8a/objs/binderhook/binder_util.o -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/binder_util.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/arm64-v8a/objs/binderhook/binder_util.o: jni/binder_util.c \ 2 | jni/include/binder.h jni/include/binder_util.h jni/include/log.h 3 | 4 | jni/include/binder.h: 5 | 6 | jni/include/binder_util.h: 7 | 8 | jni/include/log.h: 9 | -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/elf_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/arm64-v8a/objs/binderhook/elf_util.o -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/elf_util.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/arm64-v8a/objs/binderhook/elf_util.o: jni/elf_util.c \ 2 | jni/include/log.h jni/include/elf_util.h 3 | 4 | jni/include/log.h: 5 | 6 | jni/include/elf_util.h: 7 | -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/entry.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/arm64-v8a/objs/binderhook/entry.o -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/entry.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/arm64-v8a/objs/binderhook/entry.o: jni/entry.c \ 2 | jni/include/hook_util.h 3 | 4 | jni/include/hook_util.h: 5 | -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/hook_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/arm64-v8a/objs/binderhook/hook_util.o -------------------------------------------------------------------------------- /obj/local/arm64-v8a/objs/binderhook/hook_util.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/arm64-v8a/objs/binderhook/hook_util.o: jni/hook_util.c \ 2 | jni/include/binder.h jni/include/binder_util.h jni/include/elf_util.h \ 3 | jni/include/log.h 4 | 5 | jni/include/binder.h: 6 | 7 | jni/include/binder_util.h: 8 | 9 | jni/include/elf_util.h: 10 | 11 | jni/include/log.h: 12 | -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/libbinderhook.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/armeabi-v7a/libbinderhook.so -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/binder_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/armeabi-v7a/objs/binderhook/binder_util.o -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/binder_util.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/armeabi-v7a/objs/binderhook/binder_util.o: jni/binder_util.c \ 2 | jni/include/binder.h jni/include/binder_util.h jni/include/log.h 3 | 4 | jni/include/binder.h: 5 | 6 | jni/include/binder_util.h: 7 | 8 | jni/include/log.h: 9 | -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/elf_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/armeabi-v7a/objs/binderhook/elf_util.o -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/elf_util.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/armeabi-v7a/objs/binderhook/elf_util.o: jni/elf_util.c \ 2 | jni/include/log.h jni/include/elf_util.h 3 | 4 | jni/include/log.h: 5 | 6 | jni/include/elf_util.h: 7 | -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/entry.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/armeabi-v7a/objs/binderhook/entry.o -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/entry.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/armeabi-v7a/objs/binderhook/entry.o: jni/entry.c \ 2 | jni/include/hook_util.h 3 | 4 | jni/include/hook_util.h: 5 | -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/hook_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EggUncle/Hermes/9d4cd954112bf6b8110d5f1776afbd4c15abf6da/obj/local/armeabi-v7a/objs/binderhook/hook_util.o -------------------------------------------------------------------------------- /obj/local/armeabi-v7a/objs/binderhook/hook_util.o.d: -------------------------------------------------------------------------------- 1 | ./obj/local/armeabi-v7a/objs/binderhook/hook_util.o: jni/hook_util.c \ 2 | jni/include/binder.h jni/include/binder_util.h jni/include/elf_util.h \ 3 | jni/include/log.h 4 | 5 | jni/include/binder.h: 6 | 7 | jni/include/binder_util.h: 8 | 9 | jni/include/elf_util.h: 10 | 11 | jni/include/log.h: 12 | --------------------------------------------------------------------------------