(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屬性的小工具新版本》