为Android应用程序读取/dev下设备而提权(一)

来源:互联网 发布:ps切图软件 编辑:程序博客网 时间:2024/06/07 20:40

倘若应用程序需要对/dev/xxx进行读写操作,就需要提升其权限。提权方法不唯一,需要根据具体需求情况而选择。归根结底,终究都落到chmod 777 /dev/xxx 上,不同的是,chmod操作被执行在何时何地,在此做个分析总结。
内核启动后会执行/system/init,传说中的系统1号进程,init程序起初的任务是初始化,包括各种mkdir来构建文件系统,得到硬件信息建立设备节点,安装SIGCHLD信号来回收僵尸进程的资源,解析init.rc启动脚本等等,然后init程序变身为property_service来管理系统的权限。我们可以下手的地方有两处: device_init和init.rc 。

init.rc

这个方案是大家用的比较多的,在其中添加chmod操作很简单不多说。

device.c

这个方案用的比较少,先了解下device.c。
device_init在/system/core/init/device.c中,详细分析如下:

  1. //分别遍历/sys/class/sys/block/sys/devices
  2. device_init()
  3. {
  4. coldboot(fd,"/sys/class");
  5. coldboot(fd,"/sys/block");
  6. coldboot(fd,"/sys/devices");
  7. }
  8.  
  9. //后面有个递归/sys下是内核生成的设备,这就相当于udev的作用
  10. do_coldboot()
  11. {
  12. if(fd>=0){
  13. write(fd,"addn",4);
  14. close(fd);
  15. handle_device_fd(event_fd);
  16. }
  17. }
  18.  
  19. //从socket里读出add处理
  20. handle_device_fd()
  21. {
  22. if(!strcmp(uevent->action,"add")){
  23. make_device(devpath,block,uevent->major,uevent->minor);
  24. return;
  25. }
  26. }
  27.  
  28. //得到设备的相关信息创建设备节点
  29. make_device()
  30. {
  31. mode=get_device_perm(path,&uid,&gid)|(block?S_IFBLK:S_IFCHR);
  32. dev=(major<<8)|minor;
  33. mknod(path,mode,dev);
  34. chown(path,uid,gid);
  35. }
  36.  
  37. get_device_perm()
  38. {
  39. if(get_device_perm_inner(qemu_perms,path,uid,gid,&perm)==0){
  40. returnperm;
  41. }elseif(get_device_perm_inner(devperms,path,uid,gid,&perm)==0){
  42. returnperm;
  43. }else{
  44. …….
  45. }
  46.  
  47. //得到devperms结构体的信息
  48. get_device_perm_inner
  49. {
  50. for(i=0;perms[i].name;i++){
  51.  
  52. if(perms[i].prefix){
  53. if(strncmp(path,perms[i].name,strlen(perms[i].name)))
  54. continue;
  55. }else{
  56. if(strcmp(path,perms[i].name))
  57. continue;
  58. }
  59. *uid=perms[i].uid;
  60. *gid=perms[i].gid;
  61. *perm=perms[i].perm;//权限位
  62. return0;
  63. }
  64. }
  65.  
  66. 这是devperms的具体内容
  67. structperms_{
  68. char*name;
  69. mode_tperm;
  70. unsignedintuid;
  71. unsignedintgid;
  72. unsignedshortprefix;
  73. };
  74. staticstructperms_devperms[]={
  75. {"/dev/null",0666,AID_ROOT,AID_ROOT,0},
  76. {"/dev/zero",0666,AID_ROOT,AID_ROOT,0},
  77. {"/dev/full",0666,AID_ROOT,AID_ROOT,0},
  78. {"/dev/ptmx",0666,AID_ROOT,AID_ROOT,0},
  79. {"/dev/tty",0666,AID_ROOT,AID_ROOT,0},
  80. {"/dev/random",0666,AID_ROOT,AID_ROOT,0},
  81. {"/dev/urandom",0666,AID_ROOT,AID_ROOT,0},
  82. {"/dev/ashmem",0666,AID_ROOT,AID_ROOT,0},
  83. {"/dev/binder",0666,AID_ROOT,AID_ROOT,0},
  84.  
  85. /*loggershouldbeworldwritable(forlogging)butnotreadable*/
  86. {"/dev/log/",0662,AID_ROOT,AID_LOG,1},
  87.  
  88. /*theseshouldnotbeworldwritable*/
  89. {"/dev/android_adb",0660,AID_ADB,AID_ADB,0},
  90. {"/dev/android_adb_enable",0660,AID_ADB,AID_ADB,0},
  91. {"/dev/ttyMSM0",0660,AID_BLUETOOTH,AID_BLUETOOTH,0},
  92. {"/dev/alarm",0664,AID_SYSTEM,AID_RADIO,0},
  93. {"/dev/tty0",0666,AID_ROOT,AID_SYSTEM,0},
  94. {"/dev/graphics/",0660,AID_ROOT,AID_GRAPHICS,1},
  95. {"/dev/hw3d",0660,AID_SYSTEM,AID_GRAPHICS,0},
  96. {"/dev/input/",0660,AID_ROOT,AID_INPUT,1},
  97. {"/dev/eac",0660,AID_ROOT,AID_AUDIO,0},
  98. {"/dev/cam",0660,AID_ROOT,AID_CAMERA,0},
  99. {"/dev/pmem",0660,AID_SYSTEM,AID_GRAPHICS,0},
  100. {"/dev/pmem_gpu",0660,AID_SYSTEM,AID_GRAPHICS,1},
  101. {"/dev/pmem_adsp",0660,AID_SYSTEM,AID_AUDIO,1},
  102. {"/dev/pmem_camera",0660,AID_SYSTEM,AID_CAMERA,1},
  103. {"/dev/oncrpc/",0660,AID_ROOT,AID_SYSTEM,1},
  104. {"/dev/adsp/",0660,AID_SYSTEM,AID_AUDIO,1},
  105. {"/dev/mt9t013",0660,AID_SYSTEM,AID_SYSTEM,0},
  106. {"/dev/akm8976_daemon",0640,AID_COMPASS,AID_SYSTEM,0},
  107. {"/dev/akm8976_aot",0640,AID_COMPASS,AID_SYSTEM,0},
  108. {"/dev/akm8976_pffd",0640,AID_COMPASS,AID_SYSTEM,0},
  109. {"/dev/msm_pcm_out",0660,AID_SYSTEM,AID_AUDIO,1},
  110. {"/dev/msm_pcm_in",0660,AID_SYSTEM,AID_AUDIO,1},
  111. {"/dev/msm_pcm_ctl",0660,AID_SYSTEM,AID_AUDIO,1},
  112. {"/dev/msm_mp3",0660,AID_SYSTEM,AID_AUDIO,1},
  113. {"/dev/smd0",0640,AID_RADIO,AID_RADIO,0},
  114. {"/dev/qmi",0640,AID_RADIO,AID_RADIO,0},
  115. {"/dev/qmi0",0640,AID_RADIO,AID_RADIO,0},
  116. {"/dev/qmi1",0640,AID_RADIO,AID_RADIO,0},
  117. {"/dev/qmi2",0640,AID_RADIO,AID_RADIO,0},
  118. {"/dev/htc-acoustic",0640,AID_RADIO,AID_RADIO,0},
  119. {NULL,0,0,0,0},
  120. };

init.c

init.rc脚本和老版本android中的init.goldfish.rc脚本很早就被parse_config_file()函数解析将脚本内容分为几个段,early-init,init,early-boot,boot,和各个服务。然后在不同的时间点上执行各个段得命令或者开启各种服务。

init.c的一段节选:

  1. intmain(intargc,char**argv)
  2. {
  3. ……
  4. mkdir("/dev",0755);
  5. mkdir("/proc",0755);
  6. mkdir("/sys",0755);
  7. mount("tmpfs","/dev","tmpfs",0,"mode=0755");
  8. mkdir("/dev/pts",0755);
  9. mkdir("/dev/socket",0755);
  10. mount("devpts","/dev/pts","devpts",0,NULL);
  11. mount("proc","/proc","proc",0,NULL);
  12. mount("sysfs","/sys","sysfs",0,NULL);
  13. ……
  14. INFO("readingconfigfilen");
  15. parse_config_file("/init.rc");
  16. //调用parse_config解析init.rc脚本
  17. //经过解析,init.rc的内容就被分为多少个段,被串在action_list链表中。
  18. //on开头的都是action类型的段,比如init段,init段用一个结构体structaction表示,其中name是init,
  19. //所有这个段内的命令,都被串在commands链表中。
  20.  
  21. action_for_each_trigger("early-init",action_add_queue_tail);
  22. //遍历action_list链表,查找name是early-init的那个action,将这个节点放在action_queue的尾部。
  23. drain_action_queue();
  24. //将action_queue尾部的节点遍历,然后删除。
  25. //就相当于遍历name是early-init的action节点内的commands链表。
  26. //就是在执行init.rc脚本中onearly-init段内的所有命令。
  27.  
  28. ……
  29. INFO("deviceinitn");
  30. device_fd=device_init();//常见必要的设备节点
  31.  
  32. property_init();//init以后的任务就是proper_service
  33.  
  34. action_for_each_trigger("init",action_add_queue_tail);//将init段,加入action_queue
  35. drain_action_queue();//执行init段得命令
  36.  
  37. ……
  38. }

本节小结

device_init其实就是linux中的udev的一个简单的替代。把/sys/下的所有内核提供的设备都安排在/dev下创建设备节点。如果要改动/dev/一些设备的权限,可以把chmod 777写在init.rc中,但是要注意写的位置,不能太早执行,不能写在early-init段内,因为那时/dev/下的设备节点还没有被创建。
在devices.c中修改的方法隐藏的较深不容易被发现,但是如果init.rc内再次修改就可能把之前的修改覆盖掉。

原创粉丝点击