Android全局可調試(ro.debuggable = 1)的一種另類改法
阿新 • • 發佈:2018-10-28
cal size kill -9 detach root img 地址 poke service
網上流傳比較多的,是重打包boot.img。讀aosp的init進程源碼,發現通過patch init進程也可以實現相同目的。
首先看一下init進程對ro只讀屬性的檢查:
/* property_service.c */ int property_set(const char *name, const char *value) { ... pi = (prop_info*) __system_property_find(name); if(pi != 0) { /* ro.* properties may NEVER be modified once set */ if(!strncmp(name, "ro.", 3)) return -1; /* 如果是只讀屬性,不允許set,返回-1 */ __system_property_update(pi, value, valuelen); } ...
從上面代碼看出,如果將“ro.”改為“\0”即空字符串,即可繞過property_set對可讀屬性的檢查。
同時為了防止誤修改,我們查看init進程是否還有其它使用“ro.”字符串的地方,只找到一處,位於check_perms函數中:
/* * Checks permissions for setting system properties. * Returns 1 if uid allowed, 0 otherwise. */ static int check_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx) { int i; unsigned int app_id; if(!strncmp(name, "ro.", 3)) name +=3; if (uid == 0) return check_mac_perms(name, sctx); ...
分析init進程的匯編代碼,發現property_set函數地址位於check_perms函數之前,因此只要修改搜索到的第一處內存即可。
使用ptrace實現,代碼如下:
kiiim@ubuntu:~/Android_prj/patch_init_process$ cat 1.c #include <stdio.h> #include <sys/ptrace.h> #include <errno.h> #include <memory.h> #include <string.h> int main(int argc, char **argv) { int rc; unsigned long maps, mape, addr, test, fake; FILE *fp; char line[512]; char *buffer, *ro; fp = fopen("/proc/1/maps", "r"); if (!fp) { perror("fopen"); return 1; } memset(line, 0, sizeof(line)); fgets(line, sizeof(line), fp); fclose(fp); rc = sscanf(line, "%08x-%08x", &maps, &mape); if (rc < 2) { perror("sscanf"); return 1; } buffer = (char *) malloc(mape - maps); 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) { test = ptrace(PTRACE_PEEKTEXT, 1, (void *) addr, 0); *((unsigned long *)(buffer + addr - maps)) = test; } ro = memmem(buffer, mape - maps, "ro.", 3); if (ro) { printf("Patching init.\n"); fake = 0; rc = ptrace(PTRACE_POKETEXT, 1, (void *)(maps + ro - buffer), &fake); if (rc < 0) { perror("ptrace"); } } free(buffer); rc = ptrace(PTRACE_DETACH, 1, 0, 0); return rc; }
編譯並在Nexus 5中運行:
$ arm-linux-androideabi-gcc 1.c -o patch_init
運行後kill掉zygote進程:
root@hammerhead:/data/local/tmp # ps |grep zygote
ps |grep zygote
root 18887 1 860616 56352 ffffffff 400e26d8 S zygote
root@hammerhead:/data/local/tmp # kill -9 18887
zygote進程結束後,會自動被init進程拉起。待zygote重啟後,執行:
root@hammerhead:/data/local/tmp # setprop ro.debuggable 1
setprop ro.debuggable 1
root@hammerhead:/data/local/tmp # getprop ro.debuggable
getprop ro.debuggable
1
以上,ro.debuggable屬性已經被修改。只要手機不重啟,此修改一直生效,手機重啟後需重新patch。
Android全局可調試(ro.debuggable = 1)的一種另類改法