Android全局可调试(ro.debuggable = 1)的一种另类改法

别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述Android全局可调试(ro.debuggable = 1)的一种另类改法相关的知识,希望能为你提供帮助。
网上流传比较多的,是重打包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.”改为“”即空字符串,即可绕过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实现,代码如下:
[email  protected]:~/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. "); 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进程:
[email  protected]:/data/local/tmp # ps |grep zygote ps |grep zygote root18887 1860616 56352 ffffffff 400e26d8 S zygote [email  protected]:/data/local/tmp # kill -9 18887

zygote进程结束后,会自动被init进程拉起。待zygote重启后,执行:

[email  protected]:/data/local/tmp # setprop ro.debuggable 1 setprop ro.debuggable 1 [email  protected]:/data/local/tmp # getprop ro.debuggable getprop ro.debuggable 1

【Android全局可调试(ro.debuggable = 1)的一种另类改法】以上,ro.debuggable属性已经被修改。只要手机不重启,此修改一直生效,手机重启后需重新patch。


    推荐阅读