
GhostLock (CVE-2026-43499) — эксплойт для ядра Android-устройств с заблокированным загрузчиком
Эксплойт ядра для Android-устройств с заблокированным загрузчиком. Обеспечивает временный root + установку KernelSU без разблокировки загрузчика и без изменения boot-образа. Автоопределение версии ядра во время выполнения с таблицей смещений для нескольких устройств.
CVE-2026-43499 — Use-After-Free в Futex PI (Priority Inheritance)
Затрагивает ядро Linux 5.7 ~ 7.1. Исправлено в стабильных версиях 6.1.175, 6.6.140, 6.12.86. Большинство Android-устройств остаются уязвимыми по состоянию на сентябрь 2026 года.
Системный вызов pselect6 копирует данные fd_set в стек ядра. В сочетании с механизмом ожидающих futex PI освобождённый стековый фрейм может быть переиспользован как структура rt_mutex_waiter. Затем ребалансировка rb-дерева при обходе PI-цепочки записывает контролируемые значения по произвольным адресам ядра.
| Устройство | SoC | Ядро | Ветка GKI | SHIFT |
|---|---|---|---|---|
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38 | android16-5 | 0 |
| OnePlus 15 (CPH2745/2747/2749) | SM8850 | 6.12.23 | android16-5 | 0 |
| OnePlus 15 (PLK110) | SM8850 | 6.12.58 | android16-6 | 0 |
| Xiaomi 17 (pudding) | SM8850 | 6.12.23 / 6.12.69 | android16-5 / android16-6 | 0 |
| OnePlus 13 (IN2060) | SM8750 | 6.6.89 | android15-8 | -2 |
| OPPO Pad 4 Pro | SM8750 | 6.6.89 | android15-8 | -2 |
| Устройство | SoC | Ядро | Примечания |
|---|---|---|---|
| OnePlus 15T (PLZ110) | SM8845 | 6.12.38 | То же ядро, что и Ace 6T |
| OPPO Reno10 Pro+ (CPH2521) | SM8475 | 5.10.236 | Компактный waiter 5.10, waiter word=0 |
| Sony Xperia 1 IV (nagara) | SM8450 | 5.10.218 | Компактный waiter 5.10, waiter word=0 |
| OPPO Find X9 Pro (PLG110) | D9400 | 6.12.23 | MediaTek, android16-5 |
| Vivo X200 Ultra (V2454A) | SM8750 | 6.6.89 | C ashmem, традиционные хуки |
| Vivo X Fold3 Pro (PD2337) | SM8650 | 6.1.124 | Компактный waiter 6.1, waiter word=3 |
| Vivo T4 | SM8650 | 6.1.145 | Компактный waiter 6.1, waiter word=3 |
Наложение стека pselect требует, чтобы освобождённый rt_mutex_waiter оказался в пределах контролируемой пользователем области stack_fds (слова 0–14). То, куда он попадёт, определяется профилями PGO/LTO компилятора, а не версией ядра. См. Раскладка стека.
| Устройство | SoC | Ядро | Причина |
|---|---|---|---|
| OPPO Find X9 Ultra | SM8750 | 6.12.58 | PGO устраняет do_futex → waiter word=14 |
| OnePlus 15 (PLK110) | SM8850 | 6.12.69 | PGO встраивает do_futex → waiter word=20 |
| OnePlus 12 | SM8650 | 6.1.141 | PGO встраивает do_futex → waiter word=13/19 |
| OnePlus 13R / Ace 5 | SM8650 | 6.1.x | OPLUS 6.1: waiter word=13 |
| realme RMX5070 | SM6650 | 6.1.141 | OPLUS 6.1: waiter word=13 |
| OPPO Pad 5 (OPD2502) | MT6878 | 6.1.134 | OPLUS 6.1: waiter word=13 |
| Motorola Edge 60 Fusion | MT6878 | 6.1.145 | Non-OPLUS 6.1: тот же результат |
| iQOO Neo 10 CN | SM8650 | 6.1.84 | Фрейм do_futex 0xD0 → waiter word=-11 |
| OPPO PKW110 | — | 5.15.180 | Фрейм do_futex 0x140 → waiter word=-29 |
| iQOO Z9 5G | — | 5.15.178 | Фрейм do_futex слишком большой |
| CPH2763 (OPPO) | — | 6.1.115 | OPLUS 6.1: PGO встроен, waiter word=24 |
| iQOO 12 | SM8650 | 6.1.145 | 6.1: waiter word=9, task/lock в обнулённой области |
Примечание о выполнимости на 6.1: Ядра OPLUS 6.1 стабильно невыполнимы из-за встраивания
do_futexпосредством PGO. Однако некоторые ядра 6.1 не от OPLUS (vivo) сохраняют стандартную цепочку вызовов и являются выполнимыми (vivo T4, X Fold3 Pro). Выполнимость необходимо проверять для каждого устройства отдельно.
Два пути получения root, выбираемых автоматически в зависимости от возможностей устройства:
Требует off_ashmem_misc_fops != 0 (C ashmem со статическим miscdevice в BSS).
PI write (mode=4) → redirect miscdevice fops to fake fops
→ configfs r/w → pipe physrw (1-byte precise kernel r/w)
→ SELinux enforcing = 0 (single byte, no policycap corruption)
→ UMH: inject work_struct into system_unbound_wq
→ root script → ksud late-load → KSU installed
Доступно на: OnePlus 13, OPPO Pad 4 Pro, устройствах с C ashmem 5.10/6.1. Недоступно на Rust ashmem (6.12 GKI) — miscdevice, размещённый в куче.
Write 1 (mode=1) → SELinux enforcing = 0 (8-byte write, corrupts adjacent bytes)
Write 2 (mode=2) → task->cred = init_cred (uid=0, all capabilities)
Root shell → ksud late-load → KSU → SELinux policy fix
После W1+W2 эксплойт патчит поле конфигурации бинарного файла политики SELinux (|= 0xC0000000 для ANDROID_NETLINK_ROUTE + GETNEIGH) и перезагружает его через /sys/fs/selinux/load, чтобы восстановить сетевое подключение.
App (seccomp) → Write 1 → mini-adb TCP → adb shell: full exploit → root
Загрузочный лаунчер предоставляется отдельным приложением GhostLock Anchor app.
При NFDS=320 функция core_sys_select выделяет 256-байтовый буфер stack_fds в стеке ядра:
stack_fds: 0 5 10 14 | 15 20 25 29
├─in─┤─out─┤─ex──┤ ├res_in┤res_out┤res_ex┤
◄── USER CONTROLLED ──►│◄── KERNEL ZEROED ──►
Эксплойт размещает поддельные поля waiter (task, lock) во входных битмапах fd_set. Для вложенного waiter в 6.12 (14 слов): максимально допустимое слово waiter = 3. Для компактного waiter в 5.10/6.1 (10 слов): максимально допустимое слово waiter = 7.
Позиция waiter зависит от глубины цепочки вызовов:
| Шаблон | Цепочка вызовов | Допустимо |
|---|---|---|
| android16-5 (6.12) | sys_futex → do_futex → fwrpi | ✅ слово waiter=2 |
| android16-6 (6.12.58) | sys_futex → do_futex → fwrpi | ✅ слово waiter=2 |
| android16-6 (6.12.69 OPLUS) | sys_futex → fwrpi (PGO inlined) | ❌ слово waiter=20 |
| android16-6 (X9 Ultra) | sys_futex → fwrpi (PGO inlined) | ❌ слово waiter=14 |
| android15-8 (6.6) | sys_futex → do_futex → fwrpi | ✅ слово waiter=2 (SHIFT=-2) |
| vivo 6.1 | sys_futex → do_futex → fwrpi | ✅ слово waiter=3 |
| OPLUS 6.1 | sys_futex → fwrpi (PGO inlined) | ❌ слово waiter=13+ |
| 5.10 OPLUS | sys_futex → do_futex → fwrpi | ✅ слово waiter=0 |
Все записи в ядро используют псевдоним линейного отображения. Загрузчик выбирает kernel_phys_load, который различается для каждого SoC:
| SoC | kernel_phys_load |
|---|---|
| SM8845 (Ace 6T, 15T) | 0xa8000000 |
| SM8750 (OnePlus 13, OPPO Pad 4 Pro) | 0xa8000000 |
| SM8650 (vivo T4, X Fold3 Pro) | 0xa8000000 |
| SM8850 (OnePlus 15, Xiaomi 17) | 0xc7800000 |
Неверное значение приводит к тихому сбою. Считайте его на рутованном устройстве:
su -c 'grep -i "Kernel code" /proc/iomem' # c7810000-... → 0xc7800000
Переопределение во время выполнения: KPHYS=0xc7800000 /data/local/tmp/a/e
/data/local/tmp/a/e # Default (shift=0)
PSELECT_SHIFT=-2 /data/local/tmp/a/e # OnePlus 13 (6.6)
Ядра 5.10 используют 0xffffffc008000000 (VA_BITS=39, отличается от значения по умолчанию 0xffffffc080000000 в 6.x). Это обрабатывается автоматически через поле kimage_text_base в записи смещений устройства.