CVE-2026-43499 临时 root → LD_PRELOAD 通道绕过 DEFEX → 无 LTO clang-12 版 kernelsu.ko → su + KernelSU Manager 全功能
状态:✅ 2026-08-12 真机验证达成(固件
F9360ZCSAIZF1,内核5.10.236-android12-9-2755199-abF9360ZCSAIZF1)本项目记录在 Bootloader 锁定 的三星设备上达成 KernelSU root 的完整可复现流程:不需要解锁 BL、不需要刷 boot.img、不需要 Odin。
TL;DR (English): This repo documents a fully device-verified jailbreak path for a locked-bootloader Samsung Galaxy Z Fold4 (SM-F9360, SM8450, kernel 5.10.236, firmware F9360ZCSAIZF1): a CVE-2026-43499 (rtmutex UAF, fixed in July-2026 firmware) exploit chain grants temporary kernel-domain root; a custom LD_PRELOAD constructor .so bypasses Samsung's DEFEX execve interceptor to init_module() a KernelSU LKM built with the exact device toolchain (AOSP clang 12.0.5 r416183b) and with LTO disabled — the two factors that make the module loadable and its init executable on this CFI/LTO hardened kernel. Result: su works (uid=0, context=u:r:ksu:s0) and KernelSU Manager v3.2.5 recognizes the kernel. Root is in-memory only: every reboot requires re-running the exploit (~3 min, scripted). All pitfalls and dead ends (fake exports, CRC patching, ksud late-load, LTO function-sections layout) are documented below.
| 项目 | 状态 |
|---|---|
临时 root(内核域 kernel:s0) | ✅ 稳定达成(连续 9 次成功) |
KernelSU 模块加载(init_module) | ✅ kernelsu ... Live (O) |
| KSU init 完整执行 | ✅ 15 个埋点 mark 全绿 |
su 命令 | ✅ uid=0(root) gid=0(root) context=u:r:ksu:s0 |
| KernelSU Manager v3.2.5 | ✅ 识别内核版本(supercall 检测通过),SELinux 强制执行模式下工作 |
| Bootloader 解锁 | ❌ 不需要 |
| 刷机/修改分区 | ❌ 不需要 |
本质限制:BL 锁 → root 是纯内存态。 每次重启后需要重跑 exploit + 重新加载模块(全流程约 3 分钟,已脚本化)。ksud 用户态 daemon 无法部署(DEFEX 拦 execve,见 §10-4),但 su / supercall / Manager 均由内核 sucompat 直接处理,不依赖 ksud。
警告:rmmod kernelsu 会让设备立即 panic 重启(RKP 保护内存上的 syscall-table 还原路径)——永远不要卸载。
fastboot oem unlock 不存在;任何持久化 root(magisk/kernel patch)都需要刷入 boot.img,而 locked BL 拒绝一切自签镜像。CONFIG_CFI_CLANG=y + Full LTO。mod->init 的唯一来源是 CFI jump-table 槽 __cfi_jt_init_module;间接调用必须走 .cfi_jt 表项,否则 CFI 检查直接 panic。__ksymtab 导出表裁掉,普通 insmod 无法解析(Unknown symbol)。IGNORE_MODVERSIONS/IGNORE_VERMAGIC 标志全部走 try_to_force_load() 死路。sarabpal-dev/IonStack-S22U(b0q / S22U,exp32 路由)。LD_PRELOAD constructor .so 是 root 域执行任意代码的唯一豁免通道。ksud late-load)就是为锁 BL 设备设计的:不刷 boot,直接运行时 init_module。┌─ Layer 1: CVE-2026-43499 临时 root
│ ionstack-q4q exploit(KASLR 泄漏 → mm reclaim → exp32 32-bit 栈 stamp
│ → CFI r/w → pipe physrw → UMH root daemon)
│ → /data/local/tmp/cve-2026-43499-root -c '<cmd>' = kernel:s0 域 root 命令通道
│
├─ Layer 2: LD_PRELOAD .so 加载通道(DEFEX 绕过)
│ DEFEX 拦截 kernel 域 execve 任何新 ELF(Killed);LD_PRELOAD 的 constructor
│ 执行豁免 → ksu-load.so 在 /system/bin/true 进程内:
│ 读 ko → /proc/kallsyms 手工重定位 201 个 UND 符号(SHN_ABS + st_value=绝对地址)
│ → vermagic patch(旧版需要)→ init_module() → 成功
│
└─ Layer 3: KernelSU 内核模块(无 LTO clang-12 版)
init 完整执行 15 mark 全绿 → sucompat (allow_shell=1) + supercall 可用
| 项目 | 值 |
|---|---|
| 型号 | SM-F9360(Galaxy Z Fold4,q4q) |
| SoC | SM8450(Snapdragon 8+ Gen 1) |
| 固件 | F9360ZCSAIZF1(≤ 2026-06 构建,含 CVE) |
| 内核 | 5.10.236-android12-9-2755199-abF9360ZCSAIZF1 |
| 设备编译器 | AOSP clang 12.0.5 (r416183b, c935d99d7cf)(/proc/version 确认) |
| 精确 vermagic | 5.10.236-android12-9-2755199-abF9360ZCSAIZF1 SMP preempt mod_unload modversions aarch64 |
不同固件 = 不同的 kallsyms / 布局 / vermagic,需要重新适配 target.h 与重编。见 §11。
clang-14/15 + focal 源 clang-12 / lld-12(/usr/bin/clang-12、/usr/bin/ld.lld-12)CC=clang HOSTCC=clang LD=ld.lld-12FryUpDoe/android_kernel_samsung_q4q(opensource.samsung.com 有 Cloudflare 反爬)exploit 基于 sarabpal-dev/IonStack-S22U(SM8450 5.10 真机 GREEN 基座,exp32 路由)。q4q 适配 = 仓库内 patches/ionstack-q4q-adapt.patch(249 行,覆盖 target.h 参数、kernelsnitch、root.c 等)。
export ANDROID_NDK_HOME=$HOME/Projects/f9360-root/tools/android-ndk-r29
cd work/ionstack-q4q # IonStack-S22U clone + 本 patch
make PROJECT=q4q-F9360ZCSAIZF1 # 注意变量名是 PROJECT= 不是 TARGET=
q4q 关键参数(已调优,勿改):
| 参数 | 值 | 为什么 |
|---|---|---|
P0_KERNEL_PHYS_LOAD | 0xa8000000 | b0q/S22U 真机值(SM8450 全系约定;0x80080000 是误对齐假阳) |
APP_KERNEL_PAGE_KSNITCH_IDENTITY_END | 0xffffff8b00000000(44GB) | 设备内存分散在 phys 33.8–39.5GB,2GB 窗口(e2s 抄来的)永远找不到 |
KERNELSNITCH_FUTEX_HASH_SIZE | 2048 | 内核 roundup_pow2(256*8)=2048,默认 4096 导致 mm leak 全失败 |
KERNELSNITCH_MTE_ENABLED | 0 | 生产内核 kasan=off,MTE 未激活 |
EXP32_STAMP_OFF | 0x58 | 反汇编推导(b0q/q4q 的 futex_wait_requeue_pi 与 compat do_ipv6_setsockopt 帧一致) |
fork 32→16 组 / APPENDED_FUTEXES 4096→1024 | — | 降低系统负载,防 LMKD SIGKILL |
KSU_LOAD_ONLY=1(root.c) | — | 跳过 fake_exports(ksu-load.so 手工重定位替代) |
产出 3 个二进制(build/q4q-F9360ZCSAIZF1/):preload .so、app .so、root helper PIE。设备端实测必须在低负载下运行(loadavg < 2.5,开机后等 1–2 分钟),高负载下 exploit 的 fork 风暴(~544 线程 + 1024 futex park 线程)会被 LMKD 静默 SIGKILL。
这是本项目最核心的可复现配方。先讲原理,再给命令。
__cfi_check_fail → 直接 panic(无 CFI_PERMISSIVE)。Ubuntu clang-12 与 AOSP clang-12 行为也略有差异,但 CFI 关闭后(见下)差异不再致命。CONFIG_LTO_CLANG_THIN=y → -ffunction-sections 拆分布局(447 个 ALLOC 小段,.text=0)→ 任何版本(连 stub)加载即内核 panic。官方 ko 是传统布局(22 段)→ 一直能加载。关 LTO 重编 → 一次成功。__cfi_check 符号 → mod->cfi_check=NULL → cfi_init 的 shadow 注册被跳过 → 调用不经 CFI 检查。但注意:mod->init 的唯一来源是 CFI jt 槽 __cfi_jt_init_module(kernel/module.c cfi_init())——非 CFI 编译且没有 jt 槽的 ko 会 "Live" 但 init 从不执行(假成功!)。clang-12 天然生成 D __cfi_jt_init_module 槽,无需手工 objcopy。# 1) 禁 per-task sysreg stack guard(Ubuntu clang-12 不支持 -mstack-protector-guard=sysreg)
# arch/arm64/Makefile: ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) → ifeq (n,y)
# 模块 stack protector 回退全局 __stack_chk_guard(kallsyms 有导出,安全)
# 2) .config 与 include/config/auto.conf 同步修改(auto.conf 是 make 实际读的):
# CONFIG_LTO_CLANG_THIN=y → # CONFIG_LTO_CLANG_THIN is not set
# CONFIG_LTO_CLANG=y → not set
# CONFIG_LTO=y → not set
# CONFIG_LTO_NONE=y
# CONFIG_CFI_CLANG=y / CONFIG_CFI_CLANG_SHADOW=y → not set
# + CONFIG_SECTION_MISMATCH_WARN_ONLY=y
# (jt 槽 .data→.init 引用会被 modpost 拦成 ERROR,必须开)