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

    倘若应用程序需要对/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中,详细分析如下:

[cpp]  view plain copy
  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,"add\n", 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. /* logger should be world writable (for logging) but not readable*/  
  86. {"/dev/log/", 0662, AID_ROOT, AID_LOG, 1 },  
  87.   
  88. /*these should not be world writable */  
  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的一段节选:
   
[cpp]  view plain copy
  1. int main(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("readingconfig file\n");  
  15.   parse_config_file("/init.rc");   
  16. //调用parse_config解析init.rc脚本  
  17. //经过解析,init.rc的内容就被分为多少个段,被串在action_list链表中。  
  18. //on开头的都是action类型的段,比如init段,init段用一个结构体struct action表示,其中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("deviceinit\n");  
  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内再次修改就可能把之前的修改覆盖掉。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值