在 Android 开发中,有一个 ADBD 服务,是为了让开发者可以调试程序。
用 adb shell 连上手机,通过 ps 命令看 adbd 进程的信息:
shell 19128 1 3448 196 ffffffff 00008294 S /sbin/adbd
此进程的父进程是 root 用户启动,然后通用 setuid 降级为 shell 用户,
看 Android 2.2 源码中的 /Android/android2.2/platform/system/core/adb/adb.c 的源代码
/* add extra groups:
** AID_ADB to access the USB driver
** AID_LOG to read system logs (adb logcat)
** AID_INPUT to diagnose input issues (getevent)
** AID_INET to diagnose network issues (netcfg, ping)
** AID_GRAPHICS to access the frame buffer
** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
** AID_SDCARD_RW to allow writing to the SD card
** AID_MOUNT to allow unmounting the SD card before rebooting
*/
gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW, AID_MOUNT };
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
/* then switch user and group to "shell" */
setgid(AID_SHELL);
setuid(AID_SHELL);
这里并没有对 setuid 等函数的操作进行正确证判断。
如何这个函数会失败呢? 经查找,当目标用户的进程数达到 RLIMIT_NPROC 这个值的时候,setuid 就会设置失败,而 AID_SHELL 用户恰好是,用户通过 adb shell 连进来的用户,相信我们可以不断的 fork,再连一下 adb,这时 adb 就不是以 shell 用户启动了,而是它的父进程的用户(root)
看到可爱的 # 号了!