KernelSU 环境下隐藏 Root 检测实战:大麦、淘宝全部正常打开

ChatGPT Image 2026年8月18日 21_12_25

 

KernelSU 环境下隐藏 Root 检测实战:大麦、淘宝全部正常打开

机型:OnePlus PJX110(OnePlus 13) · Android 16 · 内核 6.1.141
适用:KernelSU(含 LKM 模式)用户,被大麦、淘宝等阿里系 App 检测到 Root 而无法打开的场景

一、前言

事情起因很简单:手机 ROOT 之后,大麦(cn.damai) 打开就提示”检测到系统处于不安全状态”之类的风险提示,直接退出;淘宝(com.taobao.taobao) 同样被阿里安全组件(SecurityGuard / 安全SDK)拦下。

这类 App 的检测手段无非那几样:

  1. 检测 su 二进制是否存在
  2. 检测 /data/adb 目录(Magisk / KernelSU 的数据目录)
  3. 检测 Root 管理器包名(com.topjohnwu.magiskme.weishu.kernelsu
  4. 检测模块挂载(/data/adb/modules
  5. 检测 Xposed / LSPosed / Frida 痕迹
  6. 检测 Bootloader 解锁状态(Key Attestation)

我的环境里其实早就装了 Shamiko(隐藏 Root 的经典模块)和 Tricky Store(绕过 Key Attestation),但大麦依然打不开。排查到最后发现:问题出在我对”新版 KernelSU 的隐藏机制”理解过时了——新版本早就没有”排除名单(DenyList)”了,而 Shamiko 在白名单模式下恰好依赖这个东西,等于完全没在工作。

这篇文章把我从”App 打不开”到”全部正常打开”的完整排查过程写下来,每一步都附上实测命令,希望能帮到同样被检测困扰的朋友。

二、环境清单

项目 版本/内容
手机 OnePlus PJX110(OnePlus 13)
系统 Android 16(ColorOS 分支)
内核 6.1.141-android14-11
Root 方案 KernelSU v3.2.4(ksud 3.2.4 / 管理器 v3.2.4,LKM 模式)
Zygisk ZygiskNext v1.3.3(zygisksu 模块)
隐藏模块 Shamiko v1.2.5(白名单模式)
认证绕过 Tricky Store v6.0.0-235(TEESimulator)
Xposed Zygisk-LSPosed v2.0.2
其他模块 RescueBrick、TA_utl、WorkSettingPro、reqable-magisk
目标 App 大麦 cn.damai、淘宝 com.taobao.taobao

内核功能状态ksud feature list):

[ENABLED (1)] su_compat     -- 允许已授权 App 通过 su 获取 Root
[ENABLED (1)] kernel_umount -- 内核自动为不需要的进程卸载模块挂载
[ENABLED (1)] sulog         -- su 日志
[DISABLED]    adb_root      -- adbd root(未开启)

三、核心认知:新版 KernelSU 的隐藏机制(先读懂再动手)

老玩家都知道,Magisk 时代隐藏 Root 的标准姿势是:把目标 App 加进 Magisk 排除名单(DenyList)+ 开 Shamiko 白名单模式

KernelSU 早期(v1.x 之前)也照搬了这套:管理器里有”排除名单”页,把 App 加进去,内核就会对这个 App 卸载模块挂载。

但是新版 KernelSU(v2/v3,ksud 3.x)把排除名单整个删掉了。 我在 GitHub 上拉了源码(tiann/KernelSU 主分支)确认:

  • 全仓库搜索 denylist / deny_list / “排除”,零结果
  • 取而代之的是 kernel/feature/kernel_umount.c 这套全局内核卸载机制

它的逻辑(读源码 kernel_umount.c 可以看得很清楚):

static bool ksu_kernel_umount_enabled = true;   // 默认开启

int ksu_handle_umount(uid_t old_uid, uid_t new_uid) {
    // 1. 有模块挂载才处理
    if (!ksu_module_mounted) return 0;
    // 2. 开关没开就跳过
    if (!ksu_kernel_umount_enabled) return 0;
    // 3. 只处理"App uid"和"隔离进程"(zygote fork 出来的)
    if (!is_appuid(new_uid) && !is_isolated_process(new_uid)) return 0;
    // 4. 白名单(已授权 Root 的 App)不卸载
    if (!ksu_uid_should_umount(new_uid) && !is_isolated_process(new_uid)) return 0;
    // 5. 只处理 zygote 子进程(防止误伤全局命名空间的进程)
    if (!is_zygote_child) return 0;
    // 6. 把 mount_list 里的挂载点全部卸载
    list_for_each_entry(entry, &mount_list, list) {
        try_umount(entry->umountable, entry->flags);
    }
}

翻译成人话:

新版 KernelSU 默认给所有普通 App 卸掉模块挂载(含 su、管理器 APK、模块目录),只有”已授权 Root 的 App”(白名单)能保留。不需要也不存在排除名单。

所以旧经验”加排除名单 + Shamiko 白名单”在新版 KernelSU 上完全失效——因为名单本身没了,Shamiko 在白名单模式下找不到任何要处理的 App,等于挂机。

这一条是整个排查中最关键的一步:先搞清楚你的 Root 方案的隐藏机制是什么版本,再谈怎么配。

四、排查全流程(每一步都实测)

步骤 0:准备工作

  • 手机已 ROOT(KernelSU)
  • Termux 里能拿到 root shell(我全程用 Termux + su 操作)
  • 建议先把关键信息存档:ksud -V、模块列表、内核功能状态

步骤 1:摸清 Root 环境

# Root 方案与版本
ksud -V                          # 输出: ksud 3.2.4
dumpsys package me.weishu.kernelsu | grep versionName   # 管理器 v3.2.4

# 已安装模块
ls /data/adb/modules/
# 输出: RescueBrick TA_utl WorkSettingPro reqable-magisk shamiko tricky_store zygisk_lsposed zygisksu

# 内核功能开关(重点看 kernel_umount)
ksud feature list

⚠️ 注意:不同 KernelSU 版本命令可能不同(老版本是 ksud denylist,新版本没有)。以 ksud --help 实际输出为准。

步骤 2:确认目标 App 的包名

pm list packages | grep -E "damai|taobao"
# 输出:
# package:cn.damai              ← 大麦
# package:com.taobao.taobao     ← 淘宝
# package:com.taobao.idlefish    ← 闲鱼(顺带发现)

# 拿 uid(后面验证要用)
pm list packages -U | grep cn.damai
# 输出: package:cn.damai uid:10421,1010421   ← 大麦的 uid 是 10421

# 解析启动入口(别猜 Activity 名,猜了会 Error type 3)
cmd package resolve-activity --brief cn.damai
# 输出: cn.damai/.launcher.splash.SplashMainActivity

步骤 3:读源码,确认隐藏机制(不读源码全靠猜会走弯路)

# 稀疏克隆 KernelSU 源码(只拉需要的目录,很快)
git clone --depth 1 --filter=blob:none --sparse https://github.com/tiann/KernelSU /tmp/ksu-src
cd /tmp/ksu-src

# 全仓搜排除名单 —— 结果:没有了
git grep -i "denylist" HEAD        # 空

# 看内核卸载实现
git show HEAD:kernel/feature/kernel_umount.c

结论在第三节已经说了:新版是”全局卸载 + 授权白名单“,没有排除名单。同时确认了几个关键事实:

  • ksu_uid_should_umount() 只对已授权 Root 的 App 返回 false(不卸载)
  • 卸载发生在 zygote fork 的 setresuid 阶段,普通 App 一出生就看不到模块挂载
  • kernel_umount 功能默认开启ksu_kernel_umount_enabled = true

步骤 4:从目标 App 的进程视角验证(本文最核心的方法)

光看源码不算数,要站在 App 的角度看它到底能”看见”什么。方法是:启动目标 App,拿到它的 pid,然后钻进它的进程视角检查。

# 启动大麦(用步骤 2 解析出来的真实入口)
am start -n cn.damai/.launcher.splash.SplashMainActivity
sleep 5
PID=$(pidof cn.damai | awk '{print $1}')
echo $PID    # 例:29946

# ① 检查模块挂载是否已从它的挂载命名空间消失
cat /proc/$PID/mounts | grep -iE "modules|ksu|magisk"
# (输出为空 = 模块挂载已被内核卸载 ✅)

# ② 检查 su 二进制对它是否可见
ls /proc/$PID/root/system/bin/su
# (No such file or directory = su 已隐藏 ✅)

# ③ 检查 Root 管理器 APK 目录对它是否可见
ls /proc/$PID/root/data/app | grep -i weishu
# (输出为空 = 管理器已隐藏 ✅)

# ④ 检查它是否有独立挂载命名空间
readlink /proc/$PID/ns/mnt
# 输出形如 mnt:[4026535821](独立命名空间 ✅)

# ⑤ 检查它的 SELinux 上下文是否正常
cat /proc/$PID/attr/current
# 输出形如 u:r:untrusted_app:s0:c165,...(普通 App 上下文 ✅)

正确读法:①②③ 都是”空/不存在”才是对的——这正是我们要的效果。

步骤 5:一次误报的教训(非常容易踩)

我第一次检查 /data/adb 时,用的命令是:

ls /proc/$PID/root/data/adb
# 居然输出了 ksu ksud lspd 三个目录!

当场以为内核隐藏失效了,差点去改 Shamiko 配置。但仔细一想:我是用 root 身份执行的这条命令——/proc/$PID/root 只是把路径解析到 App 的命名空间里,真正做权限检查的依然是我的 root 凭据。root 当然什么都能读!

正确做法是用 App 自己的 uid 去探测(KernelSU 的 su 支持切到任意 uid):

# 大麦 uid = 10421
su 10421 -c 'ls -ld /data/adb'
# 输出: drwx------ 11 root root ... /data/adb
#        (能 stat 到,但下面的 ls 会…)

su 10421 -c 'ls /data/adb'
# 输出: ls: /data/adb: Permission denied  ✅ 这才是 App 的真实视角

真实情况:/data/adbdrwx------ root root + u:object_r:adb_data_file:s0,普通 App 根本进不去,Permission denied 就是它唯一能得到的答案。用 root 身份测试会得到完全错误的结论。

方法论总结:验证”App 能看到什么”,就必须以 App 的 uid/SELinux 上下文去测。用 root 测等于白测。

步骤 6:重启一次,问题消失

所有验证都显示”内核隐藏已生效”,但 App 依然打不开。这时候我做了一件简单的事:重启手机

重启之后:

  • 大麦正常打开,正常登录、浏览 ✅
  • 淘宝正常打开 ✅(同一套机制,顺带也解决了)

复盘为什么重启是关键:

  1. 重启前系统处于”修复过环境”的中间状态(之前 gateway 进程曾以 root 身份运行、目录属主混乱、还遇到过 app_process 链接 libmediandk.so 失败的怪问题),zygote 和内核模块状态不干净
  2. 重启后内核模块、zygote、挂载命名空间全部从干净状态初始化,kernel_umount 在每次 zygote fork 时稳定生效
  3. 之前 App”检测到 Root”很可能就是因为某个进程/挂载状态残留被阿里安全 SDK 抓到

结论:改完隐藏相关的任何配置(模块、内核功能、属主),都建议重启一次再验证。 重启是最便宜也最彻底的”状态重置”。

五、最终生效的配置清单

以下是我这台机器上最终生效的组合(不是全部必要条件,但值得参考):

组件 状态 作用
KernelSU v3.2.4 kernel_umount ✅ 默认开启 内核级:为普通 App 卸载模块挂载、隐藏 su、隐藏管理器 APK
Shamiko v1.2.5 ✅ 白名单模式 兜底:隐藏 Xposed 痕迹等(新版内核下不依赖排除名单)
Tricky Store v6.0.0 ✅ 已安装 绕过 Key Attestation,处理”Bootloader 已解锁”检测
ZygiskNext v1.3.3 ✅ 已安装 Shamiko / LSPosed 的运行底座
Zygisk-LSPosed v2.0.2 ✅ 已安装 可选,装其他模块用(注意它本身是检测目标之一)

几个补充说明:

  • kernel_umount 是这一切的地基,它由内核实现,App 层面几乎无法对抗(除非检测到内核模块本身)
  • Tricky Store 负责”身份”层面(Play Integrity / Key Attestation),和”痕迹”层面的隐藏互补
  • 我没有动 Shamiko 的配置(保持白名单模式),也没有新增任何模块——问题不在模块数量,而在机制理解

六、注意事项与 FAQ

Q1:为什么我加了排除名单还是被检测?
先确认你的 KernelSU 版本:ksud -V。v2/v3 已经没有排除名单功能,旧教程不适用。Magisk 用户不受影响(Magisk 的排除名单还在)。

Q2:Shamiko 还需要吗?
需要,作为兜底。但要注意:Shamiko 的白名单/黑名单模式语义依赖”名单”存在。在新版 KernelSU 上白名单模式可能什么都不处理(我当时就是这状态),是否要改成黑名单模式请先测试 Termux 等需要 Root 的 App 是否还能正常 su

Q3:为什么验证时用 root 身份会误判?
/proc/<pid>/root/... 只切换”路径解析的根”,不切换”权限检查的身份”。要测 App 的真实可见性,用 su <app_uid> -c '...'

Q4:淘宝能开,别的 App 呢?
同一套机制对绝大多数 App 有效。银行类 App 如果还检测,多半是 Key Attestation 层面(检查 Tricky Store 配置)或检测到 Zygisk/LSPosed 本身。

Q5:会不会影响保修/OTA?
ROOT 本身就会破坏完整性校验,与本方案无关。KernelSU(LKM 模式)一般可以无痕卸载,但这是另一个话题。

七、命令速查表

# 环境
ksud -V                          # KernelSU 版本
ksud feature list                # 内核功能开关
ls /data/adb/modules/            # 模块列表
dumpsys package me.weishu.kernelsu | grep versionName   # 管理器版本

# 目标 App
pm list packages | grep -E "damai|taobao"        # 找包名
pm list packages -U | grep cn.damai              # 拿 uid
cmd package resolve-activity --brief cn.damai    # 解析启动入口
am start -n <入口>                               # 启动

# 进程视角验证(PID=目标进程)
cat /proc/$PID/mounts | grep -iE "modules|ksu|magisk"   # 模块挂载(空=已隐藏)
ls /proc/$PID/root/system/bin/su                          # su(不存在=已隐藏)
ls /proc/$PID/root/data/app | grep -i weishu              # 管理器(空=已隐藏)
readlink /proc/$PID/ns/mnt                                # 独立命名空间
cat /proc/$PID/attr/current                               # SELinux 上下文

# 以 App uid 验证(关键!)
su <app_uid> -c 'ls /data/adb'      # Permission denied = 正常(进不去)
su <app_uid> -c 'ls /system/bin/su'  # No such file = 已隐藏

# 源码研究
git clone --depth 1 --filter=blob:none --sparse https://github.com/tiann/KernelSU
git grep -i "denylist" HEAD          # 新版 KernelSU:查无此功能
git show HEAD:kernel/feature/kernel_umount.c   # 内核卸载实现

八、结语

这次排查看似折腾,其实核心就三件事:

  1. 读懂你的 Root 方案的隐藏机制(新版 KernelSU = 内核全局卸载 + 授权白名单,没有排除名单)
  2. 用正确的方法验证(以 App 自己的身份去探测,别用 root)
  3. 改完配置记得重启(干净的状态比堆模块更重要)

最后送上一句这次踩坑换来的心得:“隐藏 Root”这件事,机制理解 > 模块数量。 装十个模块不如搞清楚内核帮你做了什么、还差什么。

希望这篇记录对你有帮助。如果 KernelSU 后续版本又有机制变化,也欢迎对照这篇的排查方法重新验证——方法论不会过时,结论会。

(本文所有命令均在 OnePlus PJX110 / Android 16 / KernelSU v3.2.4 上实测通过)

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容