(1) 前提html
下载mprop文件点这里。使用以前请确保如下几点:linux
如 u:r:su:s0或其余能够ptrace init进程且有设置ro.xx目标属性selinux权限的domain。android
(2) 用法shell
adb shell getprop [key]用于查看手机自己的系统属性。app
adb shell setprop [key] [value]用于设置手机自己的系统属性。dom
adb push ./mprop /data/local/tmp/。推送文件到手机工具
adb shell su。切换到su模式ui
chmod 755 /data/local/tmp/mprop。赋予755权限debug
data/local/tmp/mprop。修改init进程中的默认逻辑,以后就能够修改ro属性rest
setprop ro.debuggable 1。设置任意ro属性,这里设置debuggable属性
改完以后用
getprop ro.debuggable
可查看debuggable的状态(并非去default.prop文件中校验)。
/data/local/tmp/mprop -r。恢复init进程中的默认逻辑,以后就没法再修改ro属性
exit。退出su模式
注意从新开机后debuggable会失效,还要从新运行修改。
针对 安卓属性系统(default.prop)的分析 请参考这里和这里。
直接ptrace init进程,对标红的ro.属性的判断逻辑进行修改或跳过,这样任意属性就均可以设置。相关目标文件是该文件:system\core\init\property_service.c*
。
static int property_set** (const char* name, const char* value) { ... prop_info* pi = (prop_info*) __system_property_find(name); if(pi != 0) { /* ro.* properties may NEVER be modified once set */ [COLOR="Red"]if(!strncmp(name, "ro.", 3)) return -1;[/COLOR] __system_property_update(pi, value, valuelen); } else { int rc = __system_property_add(name, namelen, value, valuelen); if (rc < 0) return rc; } ... }
#include <unistd.h> #include <ctype.h> #include <stdio.h> #include <errno.h> #include <memory.h> #include <string.h> #include <sys/ptrace.h> #include <sys/system_properties.h> #define PROP_NAME_MAX 32 #define PROP_VALUE_MAX 92 static void dump_hex(const char *buf, int len) { const uint8_t *data = (const uint8_t *) buf; int i; char ascii_buf[17]; ascii_buf[16] = '\0'; for (i = 0; i < len; i++) { int val = data[i]; int off = i % 16; if (off == 0) printf("%08x ", i); printf("%02x ", val); ascii_buf[off] = isprint(val) ? val : '.'; if (off == 15) printf(" %-16s\n", ascii_buf); } i %= 16; if (i) { ascii_buf[i] = '\0'; while (i++ < 16) printf(" "); printf(" %-16s\n", ascii_buf); } } #define ORI_INST 0x2e6f72 #define HACK_INST 0x2e6f73 int main(int argc, char **argv) { FILE *fp; int m, rc; int patch_count; unsigned long maps, mape, addr, mlen; unsigned long real_val, real_vaddr; char perms[5]; char line[512]; char *buffer, *ro; char *name = NULL, *value = NULL; uint32_t tmp; uint32_t dest_inst = ORI_INST; uint32_t mod_inst = HACK_INST; int restore = 0, verbose = 0; for (m = 1; m < argc; m++) { if (argv[m] == NULL) continue; if (argv[m][0] != '-') break; if (argv[m][1] == 'r') { restore = 1; dest_inst = HACK_INST; mod_inst = ORI_INST; } else if (argv[m][1] == 'v') { verbose = 1; } } if (restore) { fprintf(stderr, "restore ...\n"); } else { if (argc - m >= 2) { // fprintf(stderr, "Usage: %s [-r] [-v] [prop_name] [prop_value]\n" // "e.g.: %s ro.debuggable 1\n", argv[0], argv[0]); name = argv[m]; value = argv[m + 1]; } fprintf(stderr, "start hacking ...\n"); } fp = fopen("/proc/1/maps", "r"); if (!fp) { perror("!! fopen "); return 1; } // 00008000-000cb000 r-xp 00000000 00:01 6999 /init memset(line, 0, sizeof(line)); while (fgets(line, sizeof(line), fp)) { int main_exe = (strstr(line, "/init") != NULL) ? 1 : 0; if (main_exe) { rc = sscanf(line, "%lx-%lx %4s ", &maps, &mape, perms); if (rc < 3) { perror("!! sscanf "); return 1; } if (perms[0] == 'r' && perms[1] == '-' && perms[2] == 'x' && perms[3] == 'p') { break; } } } fclose(fp); fprintf(stderr, "target mapped area: 0x%lx-0x%lx\n", maps, mape); mlen = mape - maps; buffer = (char *) calloc(1, mlen + 16); if (!buffer) { perror("!! malloc "); return 1; } rc = ptrace(PTRACE_ATTACH, 1, 0, 0); if (rc < 0) { perror("!! ptrace "); return rc; } for (addr = maps; addr < mape; addr += 4) { tmp = ptrace(PTRACE_PEEKTEXT, 1, (void *) addr, 0); *((uint32_t * )(buffer + addr - maps)) = tmp; } if (verbose) { dump_hex(buffer, mlen); } for (m = 0; m < mlen; ++m) { if (dest_inst == *(uint32_t * )(buffer + m)) { // 72 6F 2E 00 == ro.\0 break; } } if (m >= mlen) { fprintf(stderr, ">> inject position not found, may be already patched!\n"); } else { real_vaddr = maps + m; real_val = *(uint32_t * )(buffer + m); fprintf(stderr, ">> patching at: 0x%lx [0x%lx -> 0x%08x]\n", real_vaddr, real_val, mod_inst); tmp = mod_inst; rc = ptrace(PTRACE_POKETEXT, 1, (void *) real_vaddr, (void *) tmp); if (rc < 0) { perror("!! patching failed "); } tmp = ptrace(PTRACE_PEEKTEXT, 1, (void *) real_vaddr, 0); fprintf(stderr, ">> %s reread: [0x%lx] => 0x%08x\n", restore ? "restored!" : "patched!", real_vaddr, tmp); } free(buffer); rc = ptrace(PTRACE_DETACH, 1, 0, 0); if (!restore && (name && value && name[0] != 0)) { char propbuf[PROP_VALUE_MAX]; fprintf(stderr, "-- setprop: [%s] = [%s]\n", name, value); __system_property_set(name, value); usleep(400000); __system_property_get(name, propbuf); fprintf(stderr, "++ getprop: [%s] = [%s]\n", name, propbuf); } return rc; }
想要很方便的对安卓源码进行分析请看这里。
参考:看雪论坛用户netsniffer的文章《修改ro属性的小工具新版本》