ShiroSU 内核提权部分讲解

25 年 7 月 4 日 星期五
879 字
5 分钟

SSU 内核是 SSU 的一部分,但其并非 SSU 的主要定位,其将会作为可选内容而存在

概述

SSU 内核部分是一个针对 Android 内核的提权与权能限制处理的部分:

  • root 提权: 注入 su 并在其被执行时在内核层面提权为 root
  • 能力管理绕过: 注入拦截能力检查函数,绕过 Linux 能力限制
  • SELinux 绕过: 注入拦截 SELinux 访问控制,允许敏感操作

目前实现方向可能为暂定


技术架构与核心机制

关键注入点与探针部署

探针类型注入函数功能说明
kprobesys_execve (按情况区分具体名称)监控 su 执行,触发提权
kretprobecap_capable绕过 Linux 能力检查
kretprobeavc_denied绕过 SELinux 访问控制

探针注册流程

flowchart TD
    A[模块加载] --> B[注册 execve kprobe]
    B --> C[注册 cap_capable kretprobe]
    C --> D[注册 avc_denied kretprobe]
    D --> E[监控/劫持敏感操作]

核心提权逻辑

伪代码,并非实际逻辑

c
struct cred *cred = (struct cred *)__task_cred(current);

// 1. 提权为 root
cred->uid = cred->euid = cred->suid = cred->fsuid = GLOBAL_ROOT_UID;
cred->gid = cred->egid = cred->sgid = cred->fsgid = GLOBAL_ROOT_GID;
cred->securebits = 0;

// 2. 赋予所有能力
memset(&cred->cap_inheritable, 0xff, sizeof(kernel_cap_t));
memset(&cred->cap_permitted, 0xff, sizeof(kernel_cap_t));
memset(&cred->cap_effective, 0xff, sizeof(kernel_cap_t));
memset(&cred->cap_bset, 0xff, sizeof(kernel_cap_t));
memset(&cred->cap_ambient, 0xff, sizeof(kernel_cap_t));

// 3. 关闭 seccomp (部分需要依情况)
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP);
current->seccomp.mode = 0;
current->seccomp.filter = NULL;

// 4. 设置 root 组
if (cred->group_info) {
    // 设置组为 root ...
}

概述:

  • UID/GID 提权: 将当前进程的所有用户用户组提权为 root=
  • 能力位全开: Linux 的 capability 机制用于细粒度权限控制,全部置 1 后进程拥有所有内核能力
  • 关闭 seccomp: seccomp 是 Linux 的系统调用过滤机制,关闭后进程可自由调用所有系统调用
  • 组信息 root 化: 将进程的 group_info 指向 root 组,避免组权限限制

SELinux 绕过机制

伪代码,并非实际逻辑

c
// avc_denied kretprobe handler

if (current->real_cred->uid.val == /* 白名单 UID */) {
    regs->regs[0] = 0;  // 白名单 UID 直接设置允许
} else if (!current->real_cred->uid.val) {
    regs->regs[0] = 0;  // root 同样设置允许
}

概述:

  • SELinux 绕过: 通过 kretprobe 注入 SELinux 的访问控制决策函数以绕过进程访问资源限制
  • UID 检查: 仅对特定 UID(如 ShiroSU 管理器 以及由用户设置的白名单 UID)或 root 生效
  • 强制放行: 将返回值设为 0,表示访问被允许,从而绕过 SELinux 的安全策略

能力检查绕过

伪代码,并非实际逻辑

c
// cap_capable kretprobe handler

if (current->real_cred->uid.val == /* 白名单 UID */) {
    regs->regs[0] = 0;  // 白名单 UID 直接设置允许
} else if (!current->real_cred->uid.val) {
    regs->regs[0] = 0;  // root 同样设置允许
}

概述:

  • cap_capable 绕过: 通过 kretprobe 注入 Linux 内核能力检查的核心函数以在能力检查返回时劫持其返回值
  • UID 检查与放行: 对指定 UIDroot 直接返回允许,绕过所有 capability 检查

进程监控与自动提权

  • 通过 kprobe 注入 sys_execve (具体地址名称需要依内核版本以及架构而定),监控进程执行 su
  • 检测到执行 su 时,自动调用提权函数实现提权为 root

伪代码,并非实际逻辑

c
char buf[128] = {0};
struct Param param;
param = *(struct Param *)regs->regs[0];
if (copy_from_user(buf, param.filename, sizeof(buf) - 1))
    return 0;

if (!strcmp(buf, "/system/bin/su")) {
    // 提权进程为 root ...
}

声明

本文章所展示的代码为 ShiroSU 内核的部分伪代码并非实际代码与实际代码会有出入伪代码仅供参考

文章标题: ShiroSU 内核提权部分讲解

文章作者: Linso

文章链接: https://oom-wg.dev/posts/ssu-ko-fund [复制]

写作时间:


商业转载请联系作者获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用 File to Download Public Resources License 进行许可。