别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述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。
推荐阅读
- Android Native Hook技术
- UI“三重天”之appium
- springboot使用遇到问题(Class “model.Address” is listed in the persistence.xml file but not mapped)
- Appium移动端自动化测试之测试应用实战
- poj3321-Apple Tree(DFS序+树状数组)
- 497. Random Point in Non-overlapping Rectangles
- Error: Default interface methods are only supported starting with Android N (--min-api 24): java.io.
- 分享一下身边朋友自学android开发及找工作的那些事!不足勿喷
- 超实用教程,教你用墨刀做出小红书app原型