Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
ghostlock-pfem10 — GhostLock (CVE-2026-43499) для OPPO Find X5 Pro (PFEM10) — реверс-инжиниринг watchdog и детектора heap-spray от OPlus | Kitploit
Инструменты/GitHubGitHub/imeiplus/ghostlock-pfem10
Безопасность AndroidПовышение привилегийКриминалистика памятиАнализ уязвимостейЭксплуатацияОбратная инженерияМобильная безопасностьРазработка Полезной НагрузкиЭксплуатация Бинарных Файлов
GitHubimeiplus/ghostlock-pfem10

ghostlock-pfem10

GhostLock (CVE-2026-43499) для OPPO Find X5 Pro (PFEM10) — реверс-инжиниринг watchdog и детектора heap-spray от OPlus

4522 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий

GhostLock — OPPO Find X5 Pro (PFEM10)

English · 中文

build

Порт GhostLock (CVE-2026-43499) для OPPO Find X5 Pro на ColorOS 16. Достигает дочернего процесса с uid=0 и загруженного kernelsu.ko; корневой процесс перехватывается.

Уязвимость

CVE-2026-43499 — use-after-free в futex PI. remove_waiter() очищает current->pi_blocked_on, когда current является requeuer, на пути отката -EDEADLK в rt_mutex_start_proxy_lock().

remove_waiter @ 0xffffffc0081ed254 — форма до исправления.

Устройство

УстройствоOPPO Find X5 Pro (PFEM10)
SoCSM8450 / Adreno 730
ОСColorOS 16.0.3.520 (CN01)
Ядро5.10.236-android12-9-o-gaf2075ad2c06
Загрузчикзаблокирован, зелёный
VA_BITS39 — KIMAGE_TEXT_BASE = 0xffffffc008000000

Статус

Этап
Триггер компактного waiter (CMP_REQUEUE_PI → EDEADLK)работает
Утечка task_struct (perf)работает
Запись PI (8 байт; значение = 0 или валидный адрес ядра)работает
task+0x778 или task+0x780 по отдельности → Uid=rootработает — но приземление на одно поле оставляет задачу расходящейся, и это скрытый жёсткий BUG_ON. См. опасность расхождения
Оба поля записаны ОДНИМ значением (согласованная пара)❌ никогда не получено с распылённой страницей. Наблюдалось только с глобальным псевдонимом init_cred (09-14, CONTROL=1). Раннер теперь это принудительно обеспечивает (SAME_VALUE=1); на устройстве не запускалось
Отмывание учётных данных (setresgid + setresuid)реализовано за V12_LAUNDER=1; на устройстве не запускалось
kernelsu.ko загруженработает
Корневой процесс выживает⚠ не установлено — см. ниже
Механизм перезагрузки❌ не установлен. Один кандидат (расхождение) теперь исключён; см. ниже
probe_state как критерий приземления❌ неверно — не использовать. Три контрпримера; см. таблицу ниже
Канал паники pstore/ramoops⚠ инструмент существует; канал никогда не проверялся (нулевого теста ещё нет)
«Жертва крутится в чистом userspace»⚠ показаний пока нет — uid.stream теперь записывает utime/stime/nvcsw, так что это можно проверить
Двойная запись за один проход со стороны pi⚠ не установлено; pi.pc/pi.left жёстко заданы как 0 в fdset_map.h
Путь A (UMH / modprobe_path)STATIC_USERMODEHELPER_PATH=""

О «корневой процесс выживает»: запуски в evidence/kill.log достигают uid=0 и загружают kernelsu.ko, и в запуске, который действительно опрашивал это, процесс менеджера KernelSU выжил 120 с, при этом kernelsu оставался Live в /proc/modules. В более позднем запуске та же цепочка оставила службы Android framework недоступными (Can't find service: package/power/input/phone/wifi), пока модуль всё ещё был Live. Ни одной строки ядра [ROOTCHECK-*] и ни одной полезной нагрузки $$sys_call_number@@ никогда не было захвачено, поэтому причина состояния более позднего запуска не атрибутирована. См. evidence/notes.md §2.3, §2.4 и §7.

Смещения

task_struct

ПолеСмещение
real_cred / cred0x778 / 0x780
кэшированный syscallno0xdf8
кэшированные uid / euid / gid / egid0xe00 / 0xe08 / 0xe10 / 0xe18

thread_info

ПолеСмещение
flags0x0
addr_limit0x8
ttbr00x10
preempt_count0x18

cred

ПолеСмещениеПолеСмещение
uid0x4cap_inheritable0x28
gid0x8cap_permitted0x30
suid0xccap_effective0x38
sgid0x10cap_bset0x40
euid0x14cap_ambient0x48
egid0x18
fsuid / fsgid0x1c / 0x20

Поток эксплуатации```

LT perf leak target task_struct → file W7 stage 1 task+0x778 = V (real_cred → private sprayed page; V observed) W7 stage 2 task+0x780 = V (cred) ★ V12_W7_VALUE=V — THE SAME VALUE, not a new page W7 stage 3 V+8 = 0 (LOCAL repair of the page that was installed, ZERO shape) LT child fexecve(memfd of loader) — no execve of a /data path loader ksud late-load → kernelsu ... Live

**Этап 2 должен явно получить значение этапа 1.** Этапы 1 и 2 — это два
независимых процесса, каждый со своим spray, поэтому «записать страницу учётных данных в оба
слота» — это ловушка: при наивном чтении это даёт `(pageA, pageB)`, и поскольку
`commit_creds` сравнивает **указатели**, эта пара является расходящейся, даже когда обе записи
происходят. Это не гипотетическая ситуация — именно это и произошло в запусках 3 и 9:```
run 9   0x778 shot  write value = 0xffffff88679bade0
        0x780 shot  write value = 0xffffff8785d6ade0     <- a different page
run 3   0x778 shot  write value = 0xffffff8787b5ade0
        0x780 shot  write value = 0xffffff881bad2de0     <- a different page

run_bootA.sh поэтому запускает stage 2 с V12_W7_VALUE=<значение, наблюдённое на stage 1> и отказывается запускать его вообще, если это значение не удаётся восстановить. HOLD должен пережить stage 2, иначе страница stage 1 освобождается и перераспределяется, и «то же самое значение» превращается в висячий указатель. См. правило одного и того же значения.

За одну загрузку восстанавливается одна страница. Stage 3 обнуляет V+8. При двух разных страницах обнуление обеих стёрло бы отпечаток gid/suid (см. ниже) и заставило бы расхождение выглядеть как согласие, поэтому раннер восстанавливает только ту страницу, которая была фактически установлена, и останавливается, если два значения расходятся.

Страница cred строится в payload.c: все восемь полей id равны нулю, все пять наборов capability заполнены, а user / user_ns / group_info указывают на root_user / init_user_ns / init_groups. Stage 3 существует потому, что побочный эффект записи всегда затирает cred+8 (gid/suid) того cred, который он устанавливает.

О init_cred — явная дихотомия

Два раздела здесь раньше противоречили друг другу («никогда глобальный init_cred» против «CONTROL=1 воспроизводит cell 2», а cell 2 и есть init_cred). Оба утверждения верны для разных ролей:

  • Запрещён как цель. Запись указателя init_cred заставляет побочный эффект повредить init_cred+8 глобально — init_cred разделяется всеми потоками ядра, и Uid: 0 0 4294967176 0 — это в точности то повреждение. Код отказывается идти по этому пути, если только V12_ALLOW_INIT_CRED=1 не задан намеренно.
  • Сохранён как единственная ДОКАЗАННО согласованная пара. Цепочка 09-14, дошедшая до ksud, записала один фиксированный адрес (0xffffff802a7e0be0) в оба слота, так что real_cred == cred по построению — именно поэтому она дожила до execve. CONTROL=1 воспроизводит это. Это контроль, а не конфигурация, на которой следует строить.

утечка perf: PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_CLOCK, PERF_SAMPLE_REGS_INTR, exclude_user=1. Принимать [0xffffff8400000000, 0xffffff90000000), голосов ≥ 15%.

Примитив записи и его побочный эффект

Скачать инструмент