TL; DR:这是一个关于最后一步的问题,在一个可移植的、面向开发人员的生根过程中,该过程适用于所有 Android 机器。它不是基于任何利用 - 这是我们作为开发人员在法律和道德上被允许对我们自己的机器做的事情。如果我得到答案并设法在我的 Debian 中进行 chroot,我将发表一篇简洁的博客文章,为所有想要 root 访问其平板电脑且不想信任可疑来源的开发人员详细介绍此过程的所有步骤“一键根”对他们的机器(僵尸网络成员?)做了什么,天知道......唯一的依赖项是机器的内核源(制造商有法律义务提供)和启动分区映像(boot.img
),99% 的情况是在制造商提供的无线更新中,或者作为独立的可闪存映像单独下载。
一周过去了,我把所有的空闲时间都花在了我的新 Android 平板电脑上。
我几乎完全成功了 - 创建了一个可移植的、面向开发人员的流程,用于在我的 Android 5.0.2 平板电脑中实现 root。
但还缺少一件事 - 我无法执行 chroot(我需要运行我的debootstrap
-ed Debian!)
到目前为止我做了什么
- 首先,我在我的平板电脑(制造商提供的)内核源代码中做了一个小补丁,然后编译了我自己的内核 - 我禁用了更改检查SELINUX 强制模式。具体来说...
在security/selinux/selinuxfs.c
:
...
if (new_value != selinux_enforcing) {
/* Commented out by ttsiodras.
length = task_has_security(current, SECURITY__SETENFORCE);
if (length)
goto out;
*/
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
"enforcing=%d old_enforcing=%d auid=%u ses=%u",
new_value, selinux_enforcing,
然后我更改了我的 initrd 映像
/default.prop
以包含:ro.secure=0
和ro.debuggable=1
由于我的制造商
initrd.img
缺少它,我也编译su.c
了https://android.googlesource.com/platform/system/extras/+/master/su/并将生成的二进制文件放在 下/sbin
,确保将其设置为 SUID root (chmod 04755 /sbin/su
)。
之后,我打包了新内核和新 initrd,正如我所解释的在我上一篇文章的第二集中- 并从我自己的镜像启动:
adb reboot boot-loader ; fastboot boot myboot.img
那么,你是 root 吗?
是的,它最初看起来很成功:
$ adb shell
shell@K01E_2:/ $ id
uid=2000(shell) gid=2000(shell) groups=1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),
3003(inet),3006(net_bw_stats)
context=u:r:shell:s0
shell@K01E_2:/ $ ls -l /sbin/su /sbin/_su
-rwxr-xr-x root root 131 2015-10-03 10:44 su
-rwsr-xr-x root root 9420 2015-10-03 01:31 _su
(the _su is the binary I compiled, set to SUID root, and "su" is
a script I wrote to tell "su" to add me to all these groups...)
shell@K01E_2:/ $ cat /sbin/su
#!/system/bin/sh
export PATH=/system/bin:$PATH
exec /sbin/_su 0,0,1000,1028,2000,2001,1004,1007,1011,1015,\
1028,3001,3002,3003,3006
现在我已经获得root权限了:
shell@K01E_2:/ $ su
root@K01E_2:/ # id
uid=0(root) gid=0(root)
groups=1000(system),1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),1028(sdcard_r),2000(shell),2001(cache),
3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats)
context=u:r:shell:s0
我 100% 确定我是 root - 不仅因为id
这么说,而且因为我还可以做正常流程绝对不能做的事情:
root@K01E_2:/ # ls -l /dev/block/platform/msm_sdcc.1/by-name/boot
lrwxrwxrwx root root 2015-10-03 10:47 boot -> /dev/block/mmcblk0p16
root@K01E_2:/ # dd if=/dev/block/mmcblk0p16 of=/dev/null bs=1M
16+0 records in
16+0 records out
16777216 bytes transferred in 0.569 secs (29485441 bytes/sec)
你瞧,我终于可以从平板电脑中读取原始分区了!
SELinux 确实处于“down,dog”模式:
root@K01E_2:/ # getenforce
Permissive
但是这里有仍然我不能做的事情:
root@K01E_2:/ # mkdir /my_mnt
root@K01E_2:/ # mount -t ext4 /dev/block/mmcblk1p2 /my_mnt
mount: Operation not permitted
也就是说,我无法挂载外部 SD 卡的 EXT4-fs 格式的第二个分区。
我也无法 chroot 到我可爱的debootstrap
-ed Debian:
root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail
Operation not permitted
是因为SELinux吗?
我不知道 - 我是 SELinux 的新手(非常新 - 才一周)。我认为当你让它进入睡眠状态(getenforce
报告“宽容”)时,它不再干扰......
显然,我错了。我们又掉进兔子洞了……
难道是因为我的流程上下文?
请记住id
返回...“uid=0(root) gid=0(root)...上下文=u:r:shell:s0”
我可以改变这个背景吗?作为root,我可以离开吗shell
?如果是这样,转向什么?
第一个问题的答案是runcon
:
shell@K01E_2:/ $ runcon u:r:debuggerd:s0 /sbin/su
root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:debuggerd:s0
好的。但什么样的背景才能让我这样做mount
呢chroot
?
阅读更多有关 SELinux 的内容,回到我的主机,我解析了/sepolicy
根目录下的文件initrd.img
:
linuxbox$ $ sesearch -A sepolicy | grep chroot
allow init_shell init_shell : capability { chown sys_chroot ...
allow init init : capability { chown dac_read_search sys_chroot ...
allow kernel kernel : capability { chown dac_override sys_chroot ...
allow asus-dbug-d asus-dbug-d : capability { chown sys_chroot ...
...
好吧,有多种可能性!尤其是那kernel
一个似乎很有希望:
shell@K01E_2:/ $ runcon u:r:kernel:s0 /sbin/su
root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:kernel:s0
root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail
Operation not permitted
该死。
到底是谁在阻止我chroot
?
任何建议都非常欢迎...
答案1
到底是谁在阻止我 chroot?
这不是 SELinux - 这是一场白费力气的追逐(getenforce
返回“Permissive”意味着 SELinux 确实不再出现在图中)。
罪魁祸首 -printk
在内核源代码中添加了相当多的内容来跟踪chroot
和的失败之后mount
- 结果是能力。更具体地说,Android 的“功能边界集” - 您可以通过man
( man 7 capabilities
) 阅读有关它们的所有内容,我承认我以前从未费心研究过它们 - 我的日常 UNIX 任务依赖于它们,但我不知道...尝试一下你的 linux 盒子你自己看看:
$ getfattr -d -m - /sbin/ping
getfattr: Removing leading '/' from absolute path names
# file: sbin/ping
security.capability=0s......
看? Ping 不再是 SUID root - 它使用信息存储在文件系统的扩展属性中知道它可以访问原始套接字层(因此它可以执行 ICMP 操作 - 即在 IP 级别)。
不管怎样,我离题了——我内核中的手术点,我停止了“放弃我的能力集”——以一种可以说是令人厌恶的“让他们全部进军”的方式——是这样的(security/commoncap.c
):
static long cap_prctl_drop(struct cred *new, unsigned long cap)
{
if (!capable(CAP_SETPCAP))
return -EPERM;
if (!cap_valid(cap))
return -EINVAL;
// ttsiodras: come in, everyone, the water's fine!
//cap_lower(new->cap_bset, cap);
return 0;
}
这意味着功能永远不会丢失 - 确实是一个非常安全的配置:-)
$ adb shell
shell@K01E_2:/ $ su
root@K01E_2:/ # chroot /data/debian/ /bin/bash
root@localhost:/# export PATH=/bin:/sbin:/usr/bin:/usr/sbin:\
/usr/local/bin:$PATH
root@localhost:/# cat /etc/issue
Debian GNU/Linux 8 \n \l
你好,我可爱的 Debian :-)
哦,“根检查器”也可以工作 - 我剪掉了“su.c”,所以我平板电脑中的每个人都可以成为根:
int main(int argc, char **argv)
{
struct passwd *pw;
uid_t uid, myuid;
gid_t gid, gids[50];
/* Until we have something better, only root and shell can use su. */
myuid = getuid();
//
// ttsiodras - Oh no, you don't :-)
//
//if (myuid != AID_ROOT && myuid != AID_SHELL) {
// fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
// return 1;
//}
现在它可以工作了,我必须让它正常工作 - 即只允许我termux
和Terminal Emulator
用户调用su
and chroot
,而不让每个人和他们的祖母参与:-)