Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
ghostlock-pfem10 — GhostLock (CVE-2026-43499) für OPPO Find X5 Pro (PFEM10) — Reverse Engineering des OPlus-Watchdog- und Heap-Spray-Detektors | Kitploit
Tools/GitHubGitHub/imeiplus/ghostlock-pfem10
Android-SicherheitPrivilege EscalationSpeicherforensikSchwachstellenanalyseExploitationReverse EngineeringMobile SicherheitPayload-EntwicklungBinary-Exploitation
GitHubimeiplus/ghostlock-pfem10

ghostlock-pfem10

GhostLock (CVE-2026-43499) für OPPO Find X5 Pro (PFEM10) — Reverse Engineering des OPlus-Watchdog- und Heap-Spray-Detektors

46vor 22 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen

GhostLock — OPPO Find X5 Pro (PFEM10)

Englisch · 中文

build

GhostLock (CVE-2026-43499)-Port für das OPPO Find X5 Pro unter ColorOS 16. Erreicht einen Kindprozess mit uid=0 und ein geladenes kernelsu.ko; der Root-Prozess wird abgefangen.

Schwachstelle

CVE-2026-43499 — futex PI Use-after-free. remove_waiter() löscht current->pi_blocked_on, wenn current der Requester ist, auf dem -EDEADLK-Rollback-Pfad von rt_mutex_start_proxy_lock().

remove_waiter @ 0xffffffc0081ed254 — Zustand vor dem Fix.

Gerät

GerätOPPO Find X5 Pro (PFEM10)
SoCSM8450 / Adreno 730
OSColorOS 16.0.3.520 (CN01)
Kernel5.10.236-android12-9-o-gaf2075ad2c06
Bootloadergesperrt, grün
VA_BITS39 — KIMAGE_TEXT_BASE = 0xffffffc008000000

Status

Phase
Kompakter Waiter-Trigger (CMP_REQUEUE_PI → EDEADLK)funktioniert
task_struct-Leak (perf)funktioniert
PI-Schreibvorgang (8 Byte; Wert = 0 oder eine gültige Kernel-Adresse)funktioniert
task+0x778 oder task+0x780 allein → Uid=rootfunktioniert — aber eine Landung auf einem einzelnen Feld lässt die Task divergieren, und das ist ein latentes hartes BUG_ON. Siehe die Divergenzgefahr
Beide Felder mit EINEM Wert beschrieben (ein konsistentes Paar)❌ nie mit einer gesprayten Seite erzeugt. Nur jemals mit dem globalen init_cred-Alias beobachtet (09-14, CONTROL=1). Der Runner erzwingt es jetzt (SAME_VALUE=1); nicht auf dem Gerät ausgeführt
Credential-Laundering (setresgid + setresuid)implementiert hinter V12_LAUNDER=1; nicht auf dem Gerät ausgeführt
kernelsu.ko geladenfunktioniert
Root-Prozess überlebt⚠ nicht nachgewiesen — siehe unten
Reboot-Mechanismus❌ nicht nachgewiesen. Ein Kandidat (die Divergenz) ist jetzt ausgeschlossen; siehe unten
probe_state als Landungskriterium❌ falsch — nicht verwenden. Drei Gegenbeispiele; siehe die Tabelle unten
pstore/ramoops-Panikkanal⚠ Instrument existiert; Kanal nie validiert (noch kein Nulltest)
„Das Opfer dreht sich im reinen Userspace"⚠ noch keine Messung — uid.stream zeichnet jetzt utime/stime/nvcsw auf, sodass es überprüft werden kann
pi-seitiger Dual-Write in einem Durchgang⚠ nicht nachgewiesen; pi.pc/pi.left sind in fdset_map.h fest auf 0 gesetzt
Pfad A (UMH / modprobe_path)STATIC_USERMODEHELPER_PATH=""

Zu „Root-Prozess überlebt": Die Läufe in evidence/kill.log erreichen uid=0 und laden kernelsu.ko, und in dem Lauf, der tatsächlich darauf pollte, überlebte der KernelSU-Manager-Prozess 120 s, wobei kernelsu weiterhin Live in /proc/modules war. In einem späteren Lauf hinterließ dieselbe Kette die Android-Framework-Dienste unerreichbar (Can't find service: package/power/input/phone/wifi), während das Modul noch Live war. Es wurde nie eine [ROOTCHECK-*]-Kernelzeile und keine $$sys_call_number@@-Nutzlast erfasst, daher wird die Ursache für den Zustand des späteren Laufs nicht zugeordnet. Siehe evidence/notes.md §2.3, §2.4 und §7.

Offsets

task_struct

FeldOffset
real_cred / cred0x778 / 0x780
gecachte syscallno0xdf8
gecachte uid / euid / gid / egid0xe00 / 0xe08 / 0xe10 / 0xe18

thread_info

FeldOffset
flags0x0
addr_limit0x8
ttbr00x10
preempt_count0x18

cred

FeldOffsetFeldOffset
uid0x4cap_inheritable0x28
gid0x8cap_permitted0x30
suid0xccap_effective0x38
sgid0x10cap_bset0x40
euid0x14cap_ambient0x48
egid0x18
fsuid / fsgid0x1c / 0x20

Exploit-Ablauf```

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

**Stage 2 muss der Wert von Stage 1 explizit übergeben werden.** Stages 1 und 2 sind zwei
unabhängige Prozesse, jeder mit seinem eigenen Spray, daher ist „schreibe die Cred-Seite in beide
Slots" eine Falle: naiv gelesen erzeugt es `(pageA, pageB)`, und weil
`commit_creds` **Zeiger** vergleicht, ist dieses Paar divergent, selbst wenn beide Schreibvorgänge
erfolgreich sind. Das ist nicht hypothetisch — genau das taten die Läufe 3 und 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 startet daher Stufe 2 mit V12_W7_VALUE=<der in Stufe 1 beobachtete Wert> und weigert sich, sie überhaupt zu starten, wenn dieser Wert nicht wiederhergestellt werden kann. HOLD muss Stufe 2 überleben, sonst wird die Seite von Stufe 1 freigegeben und neu zugewiesen, und „derselbe Wert" wird zu einem Dangling Pointer. Siehe die Gleicher-Wert-Regel.

Eine Seite pro Boot wird repariert. Stufe 3 nullt V+8. Bei zwei verschiedenen Seiten würde das Nullsetzen beider den gid/suid-Stempel (unten) löschen und eine Divergenz wie Übereinstimmung aussehen lassen, daher repariert der Runner nur die Seite, die tatsächlich installiert wurde, und stoppt, wenn die beiden Werte nicht übereinstimmen.

Die Cred-Seite wird von payload.c erstellt: alle acht ID-Felder null, alle fünf Capability-Sets voll, und user / user_ns / group_info zeigen auf root_user / init_user_ns / init_groups. Stufe 3 existiert, weil der Seiteneffekt des Schreibens immer cred+8 (gid/suid) des jeweiligen Creds überschreibt, das installiert wird.

Über init_cred — eine explizite Dichotomie

Zwei Abschnitte hier widersprachen sich früher gegenseitig („niemals das globale init_cred" vs. „CONTROL=1 reproduziert Zelle 2", und Zelle 2 ist init_cred). Beide Aussagen gelten für unterschiedliche Rollen:

  • Als Ziel verboten. Das Schreiben des init_cred-Zeigers lässt den Seiteneffekt init_cred+8 global beschädigen — init_cred wird von jedem Kernel-Thread geteilt, und Uid: 0 0 4294967176 0 ist genau diese Beschädigung. Der Code verweigert diesen Pfad, es sei denn V12_ALLOW_INIT_CRED=1 wird absichtlich gesetzt.
  • Als einziges BEWIESENES konsistentes Paar beibehalten. Die 09-14-Kette, die ksud erreichte, schrieb eine feste Adresse (0xffffff802a7e0be0) in beide Slots, sodass real_cred == cred konstruktionsbedingt gilt — deshalb überlebte sie bis execve. CONTROL=1 reproduziert dies. Es ist eine Kontrolle, keine Konfiguration, auf der aufgebaut werden sollte.

perf leak: PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_CLOCK, PERF_SAMPLE_REGS_INTR, exclude_user=1. Akzeptiere [0xffffff8400000000, 0xffffff90000000), Stimmen ≥ 15%.

Das Schreib-Primitiv und sein Seiteneffekt

Tool herunterladen