## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-JINGMATRIX-PIXEL-KSU-ROOT
# pixel-ksu-root
Инструмент, управляемый через adb, который превращает стоковый Google Pixel с заблокированным загрузчиком в устройство с root-доступом KernelSU без разблокировки загрузчика или изменения boot-образа. С хоста он запускает непривилегированный userspace-эксплойт ядра на устройстве для получения временного доступа на чтение/запись к ядру, использует этот примитив для патча root-учётных данных, а затем выполняет позднюю загрузку загружаемого модуля ядра KernelSU (`kernelsu.ko`) в работающее GKI-ядро и передаёт управление уже установленному менеджеру KernelSU (KernelSU, KernelSU-Next, SukiSU или другому варианту). Он нацелен на Pixel с Android 17 на ядрах GKI 6.1 и 6.6 и управляет всем процессом через `adb shell` для детерминированной последовательности действий и журналирования с временными метками.
## Как это работает
### (a) Userspace-эксплойт ядра → временный доступ R/W к ядру
Полезная нагрузка на устройстве — это вендорный полный цепочечный LPE для CVE-2026-43499 («GhostLock»), use-after-free в стеке при наследовании приоритета futex/rtmutex в `kernel/locking/rtmutex.c`. На пути отката requeue-PI функция `remove_waiter()` очищает `pi_blocked_on` у requeuer'а (`current`), а не у фактического ожидающего, оставляя висячий указатель на освобождённый слот в стеке ядра, который содержал `rt_mutex_waiter`. Ошибка достижима из обычного непривилегированного процесса:
1. Три потока (`owner`, `waiter`, `consumer`) строят PI-цепочку; ожидающий паркуется на `FUTEX_WAIT_REQUEUE_PI`, главный поток запускает `FUTEX_CMP_REQUEUE_PI`, а `sched_setattr` от consumer'а запускает откат.
2. Освобождённый слот в стеке перехватывается контролируемым `pselect()`/`select()` (или маршрутом `TCP_ZEROCOPY_RECEIVE` на некоторых целях 6.1), чьи слова `fd_set` ложатся поверх структуры ожидающего, записывая поддельный плоский `rt_mutex_waiter`, так что висячий указатель проходит по контролируемым атакующим полям rb-tree и lock — единый примитив контролируемой записи указателя.
3. Побочный канал занятости KernelSnitch (тайминг коллизий в хэш-таблице futex) восстанавливает адрес кучи ядра/прямого отображения для поиска slab-страницы, содержащей распылённые объекты `mm_struct`//.
Затем состояние root и SELinux патчится через канальный примитив: `cred` корневого дочернего процесса обнуляется до uid/gid 0 с полными наборами capability, его SELinux `osid`/`sid` устанавливаются в `SECINITSID_KERNEL`, seccomp очищается, а `selinux_state.enforcing` устанавливается в 0.
Цепочка эксплойта, оракул KASLR и побочный канал KernelSnitch происходят из исследования NebuSec _IonStack Part II — GhostLock_ (PoC `NebuSec/CyberMeowfia`, Apache-2.0), адаптированного здесь для Pixel/aarch64. См. Атрибуция и лицензия.
### (b) Двухфазная обработка KASLR
Ровно одна стадия цепочки может вызвать панику ядра: вывод сдвига KASLR, который соревнуется за страницу, которую, как он надеется, перехватил. Все остальные стадии безопасны для повтора, а база текста ядра фиксирована на время одной загрузки. Хост-процесс разделяется по этому свойству:
* **Фаза A — вывод базы (рискованно, один раз за загрузку).** Полезная нагрузка запускается без `KASLR_BASE` в своём окружении. Запись поддельного ожидающего перенаправляет `ctl_table.data` sysctl `random_table` на известный указатель текста ядра; чтение `/proc/sys/kernel/random/boot_id` утекает его через `proc_do_uuid()`, а вычитание смещения образа даёт `_stext`/базу KASLR. `restore_slide_boot_id()` восстанавливает повреждённый `ctl_table.data`. Поскольку проигранная гонка перезагружает устройство, ожидание загрузки предшествует каждой попытке, а проверка живости классифицирует исчезновение как панику. При успехе журнал устройства выдаёт `slide-kaslr-ok pid=<pid> base=<hex>`, и база привязывается к текущей загрузке.
* **Фаза B — повтор против базы (безопасно, повтор до root).** Полезная нагрузка перезапускается с экспортированным `KASLR_BASE=0x<base>`. Этот путь никогда не вызывает панику и зацикливается, пока `id` не сообщит через временный su.
### (c) Управляемый ядром выбор цели/полезной нагрузки и повторное использование GKI/KMI
Подключённое устройство сопоставляется с `data/targets.json` во время выполнения; ничего не захардкожено под устройство. Выполняются два независимых сопоставления:
* **Полезная нагрузка (группа смещений)** выбирается по кодовому имени устройства + сборке, поскольку устройства с одним ядром могут требовать разных смещений. Сопоставление многоуровневое: точное кодовое имя+сборка, затем только кодовое имя, затем любая запись с тем же префиксом ядра. Если полезная нагрузка не находится, процесс прерывается, а не запускает несоответствующий эксплойт.
* **KMI** всегда берётся из работающего ядра (`uname -r`), либо из совпавшей записи цели, либо выводится из строки релиза (например, `android14-6.1`).
Повторное использование одной полезной нагрузки на многих устройствах следует из структуры GKI/KMI. Каждое устройство на одной сборке GKI запускает побайтово идентичный `vmlinux`, а смещения полей структур (`task_struct->cred`, `cred->uid`, …) заморожены на время жизни ветки KMI контрактом типов KMI и принудительной проверкой CRC `MODVERSIONS`. Абсолютные адреса символов ядра, напротив, определяются линковщиком для каждой сборки `ab<NNN>`, поэтому фиксированные смещения эксплойта принадлежат одному конкретному `vmlinux`; разные образы ядра требуют разных полезных нагрузок, даже если их KMI совпадает. `data/targets.json` кодирует именно это: многие устройства дедуплицируются на одну полезную нагрузку, ключом которой является образ ядра, а отличающийся образ ядра получает свою собственную.
### (d) Поздняя загрузка LKM KernelSU с производным от менеджера и совпадающим по подписи ksud
Поздняя загрузка LKM требует GKI-ядра (5.10+) с поддержкой загружаемых модулей и совпадающего по KMI `.ko`. Модуль ядра KernelSU аутентифицирует свой менеджер, проверяя в ядре блок подписи v2 APK менеджера и сравнивая SHA-256 сертификата подписи с парой `KSU_EXPECTED_SIZE`/`KSU_EXPECTED_HASH`, скомпилированной в `.ko`. Поэтому `kernelsu.ko`, поставляемый в релизе менеджера, и APK этого менеджера разделяют одну личность подписи; несоответствующий ksud загружает драйвер, но никогда не устанавливает бит авторизации менеджера, оставляя устройство без рабочего root.
Процесс соблюдает эту связь: он определяет путь к APK установленного менеджера (`pm path <package manager>`), вытягивает APK, извлекает `lib/arm64-v8a/libksud.so` как бинарник ksud, а если менеджер не установлен — прерывается. Удерживая временный root, этот ksud размещается как исполняемый файл, принадлежащий root, и вызывается как `ksud late-load --kmi <kmi> --package-name <package manager>`. Поздняя загрузка определяет текущий KMI, вытягивает `"{kmi}_kernelsu.ko"` из своих встроенных ресурсов, выполняет ручную релокацию символов (разрешая каждый символ `SHN_UNDEF` через `/proc/kallsyms`, переписывая записи в `SHN_ABS`) и вызывает `init_module(2)` на пропатченном буфере. Затем она выполняет остальной конвейер инициализации загрузки (установка ksud, restorecon, загрузка `sepolicy.rule` и root-профилей, запуск скриптов `post-fs-data`/stage, монтирование оверлея модулей).
### (e) Проверка на основе системных вызовов
Поздняя загрузка демонизируется и повторно включает SELinux в своём форкнутом дочернем процессе, который разрушает демон временного su эксплойта; поэтому проверка не должна идти через su. Вместо этого загруженный драйвер опрашивается напрямую через его поверхность системных вызовов, доступную из обычной оболочки без root: опрашивается `ksud debug version` и анализируется сообщённая версия ядра. Непустая, ненулевая версия подтверждает, что драйвер резидентен и отвечает. Путь установки драйвера — это механизм `reboot(2)` magic → install-fd → `KSU_IOCTL_GET_INFO` (`reboot(0xDEADBEEF, 0xCAFEBABE, 0, &fd)` устанавливает анонимный fd `[ksu_driver]`; `GET_INFO` возвращает `{version, flags, features, uapi_version}`), с устаревшим каналом `prctl(0xDEADBEEF, …)` в качестве запасного. Тот же зонд при запуске сокращает весь процесс, когда модуль уже резидентен для текущей загрузки.
### (f) Разбор временного стейджинга
Эксплойт размещает свой временный su в `/apex/com.android.virt/bin/su` на tmpfs, смонтированной поверх этого каталога bin apex внутри пространства имён монтирования adbd, потому что этот каталог предшествует `/system/bin` в `PATH` оболочки — так что голый `su` в `adb shell` достигает временного, пока идёт процесс. Затем поздняя загрузка разрушает демон временного su (см. (e)) без удаления тени, что оставляет голый `adb shell su` запускающим осиротевший клиент, который завершается с `su: connect daemon: Permission denied`, даже несмотря на то, что root работает, и скрывает реальные бинарники apex (`crosvm`, `virtmgr`, `vm`, …). Как только проверка сообщает о живом драйвере, процесс размонтирует tmpfs стейджинга — через собственный `/system/bin/su` KernelSU, поскольку демон эксплойта уже ушёл — удаляет клиент временного su, сокет и журнал и сообщает, какой `su` теперь разрешает обычный . Это best-effort: при сбое он предупреждает с ручной командой вместо провала запуска, а перезагрузка очищает монтирование в любом случае.
## Использование
### Предварительные требования
* `adb` на хосте, с авторизованным устройством (включена отладка по USB).
* Стоковый Google Pixel с **заблокированным** загрузчиком на прошивке/ядре, покрытых Поддерживаемыми устройствами. Никакой разблокировки, никакого кастомного boot-образа.
* Уже установленный менеджер KernelSU (KernelSU, KernelSU-Next, SukiSU или другой вариант). Его APK — источник совпадающего ksud и его встроенного `kernelsu.ko`.
* Предварительно собранные полезные нагрузки эксплойта в `artifacts/exploits/` (см. Сборка полезных нагрузок).
### Команды
root@kitploit:~
# Одно устройство на adb; менеджер установлен; полезные нагрузки собраны.
bin/pixel-ksu-root
Драйвер сопоставляет устройство с `data/targets.json`, выполняет двухфазный процесс KASLR, выполняет позднюю загрузку модуля через производный от менеджера ksud и проверяет через системный вызов драйвера. Он завершается с ненулевым кодом, если для устройства не находится полезная нагрузка, если менеджер не установлен или если проверка никогда не сообщает о живом драйвере.
### Переменные окружения
* `KASLR_BASE=0x<hex>` — передаётся полезной нагрузке устройства во время Фазы B для повтора против фиксированной, уже выведенной базы для текущей загрузки. Не установлена во время Фазы A, чтобы полезная нагрузка выводила базу сама.
* `ANDROID_NDK_HOME` — путь к Android NDK, требуется только при сборке полезных нагрузок.
* `API` — уровень API Android для тулчейна NDK при сборке полезных нагрузок (по умолчанию 35).
## Структура проекта
root@kitploit:~
pixel-ksu-root/
├── bin/ Точка входа хост-драйвера (процесс, управляемый adb)
├── data/
│ └── targets.json Таблица сопоставления устройство→полезная нагрузка и устройство→KMI
├── exploit/ Исходный код вендорной полезной нагрузки CVE-2026-43499
│ ├── Makefile Сборка aarch64 NDK по целям
│ ├── src/ Базовый набор исходников android15-6.6
│ │ ├── main.c slide.c fops.c pipe.c root.c preload.c util.c
│ │ ├── su_daemon.c Хелпер временного su, порождаемый цепочкой
│ │ ├── kernelsnitch/ Заголовки побочного канала занятости futex-хэша
│ │ └── targets/ target.h для каждого устройства+сборки (смещения ядра)
│ └── src/61/ Набор исходников android14-6.1 (slide61.c, TCP-маршрут)
├── lib/ Общие функции оболочки/хелперы на стороне хоста
├── scripts/
│ └── build-payloads.sh Собирает и дедуплицирует набор полезных нагрузок
├── artifacts/
│ └── exploits/ Собранные, дедуплицированные .so файлы полезных нагрузок
└── docs/ Заметки по дизайну и анализу
## Сборка полезных нагрузок
`scripts/build-payloads.sh` оборачивает `exploit/Makefile` по целям и выдаёт дедуплицированный набор полезных нагрузок, названный в `data/targets.json`, в `artifacts/exploits/`. Он собирает один `.so` на уникальную группу смещений (из цели `build_from` этой группы), а не по одному на устройство.
root@kitploit:~
export ANDROID_NDK_HOME=/path/to/android-ndk # должен содержать тулчейн aarch64 NDK
scripts/build-payloads.sh # собирает каждую полезную нагрузку в data/targets.json
Makefile выбирает тулчейн Clang aarch64 NDK из `ANDROID_NDK_HOME` и компилирует по одной цели за раз; `API` (по умолчанию 35) выбирает драйвер `aarch64-linux-android<API>-clang`. Набор исходников выбирается по семейству ядра — цели `android15-6.6` компилируют базовый `src/`, цели `android14-6.1` компилируют `src/61/` — а абсолютные смещения ядра каждой цели берутся из `src/targets/<codename>-<build>/target.h`. Для прямой сборки одной цели:
root@kitploit:~
make -C exploit TARGET=husky-CP2A.260705.006
## Поддерживаемые устройства
`data/targets.json` перечисляет **19 записей устройство/сборка, покрывающих 18 моделей Pixel** (bluejay встречается на двух сборках прошивки), сгруппированных в **5 полезных нагрузок со смещениями ядра**. Выбор по образу ядра, поэтому устройства, разделяющие `vmlinux`, дедуплицируются на одну полезную нагрузку; отличающийся образ ядра получает свою собственную.
Устройства на общем образе ядра `android14-6.1-a` (`6.1.157-android14-11-gbd23337e42e7-ab14791245`) охватывают семейства Pixel 6/6 Pro/6a, 7/7 Pro/7a, 8/8 Pro и 9/9 Pro/9 Pro XL/9 Pro Fold; `android14-6.1-b` и `android14-6.1-akita` изолируют модели на том же KMI, чья сборка ядра или смещения отличаются; `android15-6.6` покрывает семейство Pixel 10.
## Атрибуция и лицензия
* **Эксплойт и техника — CVE-2026-43499 «GhostLock»:** NebuSec (Nebula Security), _IonStack Part II — GhostLock_ , выпущено в репозитории `NebuSec/CyberMeowfia` под **Apache-2.0** ; обнаружение приписано инструментарию VEGA от NebuSec, раскрыто 2026-07-07.
* **Адаптация для Pixel/aarch64:** вендорное дерево `exploit/` добавляет смещения целей `android14-6.1` и `android15-6.6` и демон поздней загрузки KernelSU поверх эксплойта NebuSec; оно не несёт отдельной лицензии и наследует условия вышестоящего Apache-2.0.
* **Побочный канал KernelSnitch:** Lukas Maar и др., TU Graz (isec-tugraz), NDSS 2025.
* **KernelSU:** проект KernelSU и его варианты предоставляют загружаемый модуль ядра, `ksud` и модель авторизации менеджера, которые этот инструмент загружает поздней загрузкой.
Вендорный исходный код в `exploit/` сохраняет свою вышестоящую лицензию (Apache-2.0 для производного от NebuSec эксплойта). Этот проект агностичен к менеджеру: он выполняет позднюю загрузку менеджера любого варианта KernelSU, который установлен, и не нацелен на какой-либо конкретный форк и не включает его.
## Ссылки
### GhostLock / CVE-2026-43499
* IonStack Part II: GhostLock — Nebula Security (исследовательский отчёт)
* Запись CVE-2026-43499 в buglist — nebusec.ai
* NebuSec/CyberMeowfia — репозиторий PoC (Apache-2.0)
* GhostLock CVE-2026-43499 — TuxCare
* 15-летний дефект GhostLock даёт root — The Hacker News
* RHSB-2026-010 GhostLock — Red Hat
### KernelSnitch
* KernelSnitch: Side-Channel Attacks on Kernel Data Structures — статья NDSS 2025 (PDF)
* KernelSnitch — страница симпозиума NDSS
* isec-tugraz/KernelSnitch — исходный код
### Поздняя загрузка LKM KernelSU и привязка менеджера
* KernelSU (вышестоящий)
* Путь поздней загрузки `ksud`
* Загрузчик `init_module` и обнаружение драйвера
* Reboot-magic install-fd и kprobe
* UAPI: магические числа, номера ioctl, структура/флаги GET_INFO
* Проверка подписи v2 APK в ядре
* Руководство по установке
* Руководство по модулям
* Интеграция non-GKI (фон встроенного/LKM)
* Спасение от bootloop (контекст boot-образа LKM)
* DeepWiki: установка и поддержка устройств
* KernelSU-Next
* KernelSU-Next `apk_sign.rs`
* Релизы KernelSU-Next
* SukiSU-Ultra
### GKI / KMI
* Схема версионирования GKI — AOSP
* Проект Generic Kernel Image (GKI) — AOSP
* Поддержание стабильного интерфейса модулей ядра — AOSP
* Мониторинг ABI ядра Android — AOSP
* Общие ядра Android — AOSP
* Обзор модулей ядра — AOSP
* FAQ по ядру Android — AOSP
* Мониторинг ABI для ядер Android — README kernel/build
* Тег kernel/common android14-6.1 — Git at Google
* Внутренности загрузки модулей — kernel-internals.org
* Анатомия загружаемого модуля ядра Linux — terenceli
* module: put modversions in vermagic (LKML)
* Лицензирование модулей ядра Linux и version magic — embeddedpathashala