网上流传比较多的,是重打包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。

最新文章

  1. js jquery中 的数据类型
  2. 希尔排序( Shell Sort)
  3. QQ音乐项目(OC版) - 实现细节
  4. Java用DOM操作xml
  5. 【HDOJ】1903 Exchange Rates
  6. SQL Server 查看一个表上的索引
  7. SAP 参照sto订单创建外向交货BAPI
  8. TCP/IP协议全解析 三次握手与四次挥手[转]
  9. java工作流引擎Jflow父子流程demo
  10. RIDE的下载及安装
  11. windows下复制文件报错“文件名对目标文件夹可能过长 。您可以缩短文件名并重试,或者......”
  12. opencontrail-vrouter命令
  13. JAVA核心技术I---JAVA基础知识(不可变对象和字符串)
  14. python学习2:turtle的使用蟒蛇绘制的学习以及自己摸索的等边三角形绘制(跟随mooc学习)
  15. 关于latex编译中文不显示问题的解决方法。
  16. 【C语言】练习3-5
  17. BZOJ 2594 水管局长数据加强版(动态树)
  18. C#通过反射获得对象所有属性和值
  19. ERROR getting &#39;android:label&#39; attribute: attribute is not a string value
  20. cocos2d 文件系统使用文件内存映射性能对比

热门文章

  1. 将本地项目推送至gitee或者github
  2. Spring注解之 @SuppressWarnings注解
  3. Analytic Functions in Oracle
  4. nodejs利用sequelize-auto 根据数据库的table 生成model
  5. 将16进制unsigned char数组转换成整数
  6. js代码之编程习惯
  7. 如何搭一个vue项目
  8. learning scala output to console
  9. JAVA的环境变量配置(方式二)
  10. 【转载】 unity 塔防游戏