
Zielgerichteter Android-CVE-2026-98260-Research-Port für Xiaomi 17 (pudding)
Eine Android-AArch64-Exploit-Kette für einen exakten Kernel-Build des Xiaomi 17 (Codename
pudding): Ausgehend von einer gewöhnlichen ADB-Shell wird SELinux nacheinander auf Permissive gesetzt, die UID/GID des aktuellen Prozesses auf Null gesetzt, vollständige Linux-Capabilities ergänzt und innerhalb des aktuellen Boot-Zyklus ein Root-Dienst bereitgestellt.
Dieses Projekt ist eine Referenz und Portierung von CVE-2026-98260-popsicle-android (Xiaomi 17 Pro Max / popsicle) und keine von Grund auf eigenständig durchgeführte Forschung.
Ein execve() aus einem Nicht-Hauptthread führt zunächst de_thread() aus, um die Thread-Identität zu tauschen. Wenn exec danach fehlschlägt (z. B. wenn exec_mmap() durch SIGKILL unterbrochen wird und -EINTR zurückgibt), beendet sich die Task, bevor POSIX-Timer bereinigt werden: Der k_itimer wird freigegeben, aber sein timerqueue-Knoten bleibt im Baum der noch lebenden Task. Wenn der Elternprozess diese Task später einsammelt, greift cleanup_timerqueue() erneut auf diesen bereits freigegebenen Knoten zu, wodurch eine Use-after-free entsteht.
Der Exploit verwandelt diese UAF in einen eingeschränkten Acht-Byte-Null-Schreibvorgang und schreitet dann in drei Schritten voran: SELinux → UID/GID → vollständige Capabilities. Eine vollständige, einsteigerfreundliche Erklärung findet sich in docs/VULNERABILITY.md.
| Projekt | Gemessener Wert |
|---|---|
| Gerät | Xiaomi 17, Modell 25113PN0EC, Codename pudding |
| System | Xiaomi HyperOS 4 OS4.0.5.0.XPCCNXM, Android 17 |
| Kernel | 6.12.69-android16-6-g43b5ab7e247d-abogki561813157-4k |
| Seitengröße | 4 KiB |
| Ausgangspunkt | Autorisierte gewöhnliche ADB-Shell, UID 2000, SELinux Enforcing, Bootloader gesperrt |
| Erfolgreiches Ergebnis | UID/GID 0, SELinux Permissive, CapPrm/CapEff/CapBnd=000001ffffffffff |
| Lebenszyklus | Der Root-Dienst steht für neue ADB-Shells im weiteren Verlauf dieses Boots zur Verfügung; nach einem Neustart muss er erneut ausgeführt werden |
Unabhängige Verifizierung nach dem Erfolg (neu geöffnete ADB-Shell):
uid=0(root) gid=0(root)
CapInh: 000001ffffffffff
CapPrm: 000001ffffffffff
CapEff: 000001ffffffffff
CapBnd: 000001ffffffffff
getenforce: Permissive
Dies ist kein dauerhafter Root. Es wird nichts in boot/init_boot oder eine andere Partition geschrieben, der Bootloader bleibt gesperrt; nach einem Neustart kehrt SELinux zu Enforcing zurück und der Root-Dienst verschwindet.
Keine Erfolgsgarantie. In Tests gelang es bei 9 Startvorgängen einmal, ein vollständiges A→B→C zu erreichen. Die Durchgangsbedingungen der drei Phasen sind voneinander unabhängig:
| Phase | Geräteseitiges Programm | Durchgangsbedingung |
|---|---|---|
| 1. SELinux | exploit-android-perf | getenforce ist Permissive, die übrigen Felder des Statusworts bleiben wie erwartet |
| 2. Identität | exploit-android-perf-chain | UID/GID desselben Prozesses werden 0, anschließend exec fullcap |
| 3. Vollständige Rechte | exploit-android-key-ptr + pc98260_rootd.c | Vollständige Capabilities, der Root-Dienst ist über eine neue Shell erreichbar |
Wird ein Schritt nicht getroffen, wird [PARKED] ausgegeben und der gefährliche Zustand bleibt bestehen; ein Neustart ist erforderlich, ein erzwungener erneuter Versuch innerhalb desselben Startvorgangs ist nicht möglich.
--aio 16384 ist der auf diesem Gerät abgestimmte Wert (der erfolgreiche Durchlauf traf auf der 3903. Perf-Metadatenseite).
| Position | popsicle | pudding |
|---|---|---|
LINK_SELINUX_STATE | 0xffffffc08289aba0 | 0xffffffc0827f9ba0 |
LINK_GETPID | 0xffffffc080074eac | 0xffffffc080102e10 |
| Timer-Adressleck | alloc_posix_timer gibt die Sonde zurück | Dieses Symbol wurde inlined, stattdessen wird der Einstiegspunkt $arg1 von posix_cpu_timer_create verwendet |
PERF_MAX | 8192 | 16384 (erhöht die Chance auf einen Seitentreffer) |
Grundlagen und Belege siehe docs/ADAPTATION.md.
Ein Android NDK wird benötigt. Das bin/ im Repository wurde mit NDK 26.3.11579264 / API 34 gebaut:
powershell -NoProfile -ExecutionPolicy Bypass -File .\build.ps1 -NdkHome "$env:LOCALAPPDATA\Android\Sdk\ndk\26.3.11579264" -ApiLevel 34
-VerifyReference vergleicht nacheinander die SHA-256-Werte der neuen Artefakte mit denen in bin/; nur bei Verwendung derselben Toolchain wie für bin/ sind sie byteidentisch. Bei einem anderen NDK-Version läuft es weiterhin, aber die Hashes unterscheiden sich.
Artefakte:
| Artefakt | Eingabe-Quellcode |
|---|---|
exploit-android-perf | src/exploit-android-perf.c |
exploit-android-perf-chain | src/exploit-android-perf-chain.c |
exploit-android-key-ptr | src/exploit-android-key-ptr.c + src/pc98260_rootd.c |
pc98260-su | src/pc98260_su.c |
Der Build verbindet sich nicht mit dem Telefon und schreibt nicht auf das Gerät.
Verbinden Sie ein Gerät, bei dem USB-Debugging aktiviert und autorisiert ist, und fügen Sie platform-tools zum PATH hinzu:
.\开始98260临时ROOT.bat
oder explizit ein Gerät angeben:
powershell -NoProfile -ExecutionPolicy Bypass -File .\run_98260.ps1 -Serial <ADB序列号> -Reboot
Das Host-Skript prüft Modell, inkrementelle Systemversion, vollständigen Kernel-String, Boot-ID und die Hashes der vier Binärdateien; außerdem setzt es vor dem Start jeder Phase /sys/kernel/tracing/tracing_on auf 0 (bei einigen HyperOS-Builds hält miuibpf es auf 1, wodurch die Exploit-Kette die Ausführung verweigert). Wenn [PARKED] erscheint, stoppt das Skript und fordert zum Neustart auf.
Nach erfolgreichem Abschluss kann root so verwendet werden:
adb shell -t /data/local/tmp/pc98260-su
adb shell /data/local/tmp/pc98260-su -c "id"
Die Exploit-Kette erfordert die präzise Rückgewinnung „der Seite, auf der sich der Ziel-Timer befindet“. Wenn dieselbe Zielseite nicht beobachtet werden kann oder die Verifikation nach dem Zeigerschreiben inkonsistent ist, behält das Programm die betreffenden Zombie-/Mappings bei und stoppt, um zu vermeiden, dass blind zurückgewonnen wird, während der hängende Knoten noch vom Kernel referenziert wird. In diesem Fall sollte ein neuer Telefonstart als Grenze für den nächsten Versuch dienen.
Dieses Repository enthält nicht: Gerätesicherungen, boot/init_boot-Images, Partitions-Images, payload.bin, aus der Firmware extrahierte Kernel/ELFs, rohe Laufzeitprotokolle, ADB-Seriennummern oder Boot-IDs. logs/ und build/ sind von Git ignoriert. In bin/ befinden sich nur die vier temporären Rechteausweitungs-Kettenbinärdateien.