Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-43499-warhol-root — Exploit di escalation dei privilegi locale che prende di mira la CVE-2026-43499 per Xiaomi 17T Pro (warhol) su Android 16 con SoC MediaTek MT6993. | Kitploit
Strumenti/GitHubGitHub/soralis0912/cve-2026-43499-warhol-root
Sicurezza AndroidEscalation di PrivilegiAnalisi delle VulnerabilitàExploitBinary Exploitation
GitHubsoralis0912/cve-2026-43499-warhol-root

CVE-2026-43499-warhol-root

Exploit di escalation dei privilegi locale che prende di mira la CVE-2026-43499 per Xiaomi 17T Pro (warhol) su Android 16 con SoC MediaTek MT6993.

Vedi Repository

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
1125 giorni faNon ancora revisionato

warhol-root

CVE-2026-43499 (IonStack) elevazione dei privilegi locale, portata su Xiaomi 17T Pro (warhol) — MediaTek MT6993, Android 16.

Solo GKI 6.12 / android16. L'overlay del waiter, il layout dello stack di pselect e ogni offset di struct sono ancorati a quel ramo, quindi nulla qui è trasferibile a 6.6, 6.1 o 5.10 — quelli richiedono una base costruita per loro. generate_target.py rifiuta qualsiasi altro banner piuttosto che emettere un header che farebbe fault sul dispositivo.

Stato: funzionante. Verificato su dispositivo il 2026-07-26 da un avvio pulito, con entrambe le varianti del preloader — uid=0(root) context=u:r:kernel:s0, SELinux permissive, su installato. Il root non è persistente: riesegui la riga LD_PRELOAD dopo ogni avvio. La race di pselect non è al 100%: un'esecuzione fallita può causare un panic del telefono, e un nuovo tentativo dopo il riavvio è normale. Vedi WARHOL_PORT.md per il registro completo.

Questo dispositivo richiede la correzione kernel-MTE. La popsicle upstream originale non riesce a ottenere root — resta bloccata in kernel page retry N/12 all'infinito. Vedi Kernel MTE.

Le build sono disponibili in due varianti di preloader, PRELOADER=retail (predefinita) e PRELOADER=eng. Selezionano directory target diverse, così nessuna può sovrascrivere gli indirizzi dell'altra — vedi Variante del preloader.


Dispositivo target

Le informazioni seguenti sono state lette dal pacchetto OTA completo retail — metadati, il manifest del payload A/B e le immagini boot/vendor_boot/dtbo estratte da payload.bin.

Il kernel conta più del SoC qui: warhol si trova sullo stesso ramo GKI della popsicle upstream (android16-5, pagine 4K), a un patchlevel di distanza — 6.12.38 rispetto alla verificata 6.12.23 della popsicle. Gli offset delle struct vanno comunque rigenerati per ogni build; solo la forma dell'exploit si trasferisce. Una build OS3.0.x diversa richiede il proprio target.h.


Perché questa base

La catena dell'exploit è bloccata alla versione del ramo GKI, non al SoC. Il layout del waiter di rt_mutex, l'overlay dello stack di pselect e gli offset della struct pipe_buffer seguono tutti il kernel, quindi una base 6.12/android16 batte una base dello stesso vendor su un ramo più vecchio.

x-spy/CVE-2026-43499-popsicle è l'unica implementazione pubblica verificata sulla linea GKI 6.12/android16 (Xiaomi 17 / Pro / Ultra, kernel 6.12.23-android16-5), quindi source/ è presa da essa e mantenuta il più vicino possibile all'upstream — a parte due righe (vedi Kernel MTE, di cui questo dispositivo ha bisogno per funzionare del tutto).

La maggior parte della differenza MediaTek è confinata alla generazione del target a build-time, in due parti:

  • l'upstream legge p0_phys_offset e p0_kernel_phys_load da una partizione Qualcomm xbl_config, che warhol non ha. generate_target.py --dtb legge invece la base della DRAM dal nodo /memory del FDT di vendor_boot, arrotondandola per difetto come fa arm64_memblock_init. L'indirizzo fisico di caricamento del kernel viene letto dalla prenotazione mb_kernel del preloader con --preloader; il delta risulta 0 per questo dispositivo, e lk rifiuta di avviare un kernel posizionato altrove.
  • MediaTek distribuisce il kernel compresso LZ4-legacy dentro boot.img invece che come Image arm64 nuda, quindi il generatore lo decompressa prima dell'analisi.

WARHOL_PORT.md §2 contiene la derivazione completa.


Variante del preloader

L'lk di MediaTek non carica il kernel a una costante di compilazione — cerca una prenotazione DRAM chiamata mb_kernel e verifica che sia finita esattamente lì. Quella prenotazione è fatta dal preloader, ed è per questo che la build del preloader in esecuzione sul telefono è un input di build: è l'unica cosa al di fuori di boot.img che può spostare P0_KERNEL_PHYS_LOAD, e un valore sbagliato lì significa un alias sbagliato della mappa lineare e un telefono morto, non un exploit fallito.

Da qui due varianti, mantenute come directory target separate:

root@kitploit:~
make preload                  # PRELOADER=retail -> out/preload-<device>.so
make PRELOADER=eng preload    #                  -> out/preload-<device>-eng.so
make both                     # both of the above, and print their sha256

Entrambi gli artefatti sono mantenuti affiancati con nomi distinti. Su questo firmware risultano byte-identici — questo è il risultato dell'analisi sotto, non una scorciatoia, quindi i due sono comunque compilati e nominati separatamente.

Leggi tu stesso le tabelle del memory layout dei due preloader con:

root@kitploit:~
python3 tools/preloader_memlayout.py <preloader.bin> --diff <preloader_eng.bin>

Per questo firmware le due tabelle sono identiche, mb_kernel.start = 0x80000000 in entrambe, quindi il target.h eng risulta byte-identico a quello retail ed entrambe le build producono lo stesso preload.so.

Ciò che arriva davvero all'exploit è la differenza P0_KERNEL_PHYS_LOAD − P0_PHYS_OFFSET, e i suoi due termini non poggiano su prove ugualmente solide:

  • P0_KERNEL_PHYS_LOAD — misurato dall'immagine eng, come mb_kernel.start sopra.
  • P0_PHYS_OFFSET — è stato dedotto più che misurato, poiché è memstart_addr, che il kernel prende dal nodo /memory che lk emette a runtime da ciò che il preloader riporta dopo l'inizializzazione della DRAM, non dal FDT statico che il generatore legge. L'argomento era che le due build condividono l'intero percorso DRAM — stesse sorgenti dramc/emi/mblock/memory_layout, nessun codice di memory layout tra le stringhe solo-eng — e che l'unica prenotazione extra del preloader eng, un security_fe_rsv dinamico da 3 MiB con mapping=1, non può né spostare una voce a indirizzo fisso né scavare un buco in fondo alla DRAM. L'esecuzione sul dispositivo lo ha risolto: gli alias della mappa lineare sono finiti sotto eng, quindi il termine è corretto.

Derivazione completa in targets/warhol-OS3.0.304.0.WPSJPXM-eng/NOTES.md.

Note dall'esecuzione sul dispositivo:

  • Il BootROM accetta questo preloader eng — si è avviato normalmente ad Android, con ro.boot.verifiedbootstate=green e flash.locked=1 invariati. Era una questione aperta finché non è stato provato; è decisa dall'hash della root key bruciata nell'efuse, e questa build è firmata con le stesse chiavi della retail.
  • Il preloader eng mantiene attiva la META / la modalità download di fabbrica: %s META DIS è una stringa solo retail, mentre eng porta un'intera implementazione META che retail non ha (Enable fastmeta., FAST META GPIO: %d, META_COM PORT: %d, read_meta_proinfo, …). Qui si è avviato direttamente ad Android, ma se un telefono con preloader eng finisse da qualche altra parte, questa è la causa probabile e nessun valore di target.h è coinvolto.
  • Se un firmware successivo sposta mb_kernel, i due target divergono — tenerli come directory separate è ciò che impedisce che questo accada in silenzio.

Kernel MTE

Questo kernel esegue KASAN_HW_TAGS — /proc/cmdline contiene kasan.stack_ring_size=524288 — quindi i puntatori slab portano un tag di allocazione nei bit 59:56. La popsicle upstream assume puntatori senza tag e quindi non può ottenere root su questo dispositivo in alcun modo: resta in loop in [-] kernel page retry N/12 mode=1 all'infinito, senza che il log dica perché.

Due righe in source/ lo risolvono, ed entrambe sono in warhol-mte-fix.patch:

Solo i controlli rimuovono il tag. I puntatori stessi restano taggati, perché il tag è quello corretto per la memoria a cui puntano — che è esattamente ciò di cui ha bisogno una dereferenziazione da kernel.

Non basarti su arm64.memtag.bootctl per questo: quella proprietà è il controllo MTE di userspace e non dice nulla sul fatto che il kernel stia taggando le proprie allocazioni.


Upstream / riferimenti

Questo repository è un port. Il credito per la catena dell'exploit va all'upstream.


Layout

root@kitploit:~
source/          exploit core (upstream popsicle + the kernel-MTE fix; see warhol-mte-fix.patch)
  src/           main.c slide.c fops.c pipe.c util.c preload.c su_daemon.c + kernelsnitch/
targets/         per-build generated target.h, one dir per fingerprint x preloader variant
  warhol-OS3.0.304.0.WPSJPXM/       PRELOADER=retail
  warhol-OS3.0.304.0.WPSJPXM-eng/   PRELOADER=eng
tools/
  payload_dump.py          extract partitions from an A/B payload.bin (verifies size+sha256)
  kernel_banner.py         read the Linux banner out of a boot.img
  bootinfo.py              dump boot / vendor_boot header fields
  generate_target.py       target.h generator; upstream's, MediaTek-only, plus kernel decompression
  preloader_memlayout.py   dump/diff a MediaTek preloader's static DRAM reservation table
  lz4legacy.py             LZ4 legacy-frame decompressor (kernel images)
out/             build artifacts (gitignored)

Build

Nulla viene compilato finché non esiste un target.h — il Makefile fallisce rumorosamente piuttosto che emettere un binario contro il kernel sbagliato.

root@kitploit:~
# 1. extract boot.img straight out of the OTA zip (payload.bin is stored uncompressed,
#    so --base seeks into the zip; no need to unpack 7.6 GB first)
python3 tools/payload_dump.py <ota.zip> --base 5081 -p boot,vendor_boot,dtbo -o <dir>

# 2. confirm the kernel banner — every offset downstream is pinned to it
python3 tools/kernel_banner.py <dir>/boot.img
python3 tools/bootinfo.py <dir>/boot.img

# 3. generate the target header. --preloader reads the kernel's physical load address
#    out of the preloader's mb_kernel reservation; pass the preloader the phone runs.
python3 tools/generate_target.py \
  --boot <dir>/boot.img --dtb <dir>/vendor_boot.img --preloader <preloader.bin> \
  -o targets/warhol-OS3.0.304.0.WPSJPXM/target.h

# 4. build
make preload            # DEVICE=warhol-OS3.0.304.0.WPSJPXM, PRELOADER=retail by default

Senza avere a disposizione un'immagine del preloader, --kernel-phys-delta 0 è la forma più vecchia e produce lo stesso header per questo firmware — ma è un'asserzione piuttosto che una lettura, quindi preferisci --preloader. Passarli entrambi fa sì che il generatore li incroci e fallisca in caso di discrepanza.

--base 5081 è l'offset del local header di payload.bin per questa specifica OTA; leggilo da ota-property-files in META-INF/com/android/metadata per qualsiasi altro pacchetto.

Richiede un Android NDK (NDK_ROOT / ANDROID_NDK_HOME) e llvm-objdump.

Esecuzione

root@kitploit:~
# <device> is the target name: <fingerprint> for PRELOADER=retail, <fingerprint>-eng for eng
adb push out/preload-<device>.so /data/local/tmp/preload.so
adb shell chmod 0644 /data/local/tmp/preload.so
adb shell "LD_PRELOAD=/data/local/tmp/preload.so /system/bin/true"
adb shell "/data/local/tmp/su -c id"

cred e lo stato di SELinux vengono patchati in memoria, quindi questo va ripetuto dopo ogni avvio. Non è richiesto lo sblocco del bootloader.


Disclaimer

Per ricerca su hardware di tua proprietà. Eseguirlo può causare bootloop o brick del dispositivo e invaliderà la garanzia. Nessuna garanzia di alcun tipo.

I progetti upstream sono licenziati dai rispettivi autori; questo port mantiene i loro termini.

Scarica lo strumento
VoceValoreSorgente
Codenamewarholpre-device=warhol
Build fingerprintXiaomi/warhol_global/warhol:16/BP2A.250605.031.A3/OS3.0.304.0.WPSJPXM:user/release-keyspost-build
IncrementalOS3.0.304.0.WPSJPXM (JP globale)post-build-incremental
Android16, SDK 36post-sdk-level=36
Patch di sicurezza2026-05-01post-security-patch-level
Tipo OTAA/B (payload.bin, CrAU, 39 partizioni)ota-type=AB
SoCMediaTek MT6993 (Dimensity 9500)compatibili mediatek,mt6993-* nel DTB di vendor_boot; cmdline bootopt=64S3,32N2,64N2
Kernel6.12.38-android16-5-g1d46253471dd-ab15048002-4k, clang 19.0.1banner letto dalla boot.img estratta
boot imageheader v4, kernel 18.898.125 B, compresso LZ4-legacy, nessun ramdisktools/bootinfo.py
PRELOADER=Preloader sul telefonoDirectory targetStato
retail (predefinito)il preloader_<device>.bin distribuito, byte-identico al preloader_raw.img della ROM fastboottargets/warhol-OS3.0.304.0.WPSJPXM/✅ verificato su dispositivo 2026-07-26
engla build engineering, preloader_<device>_eng.bintargets/warhol-OS3.0.304.0.WPSJPXM-eng/✅ verificato su dispositivo 2026-07-26
FileModificaPerché
src/util.ckernelsnitch_setup(..., mte_enabled=1)con 0, la ricerca di mm_struct prova solo candidati senza tag e non può mai raggiungere un puntatore con tag — un errore strutturale, non sfortuna
src/util.cis_kernel_ptr() / is_direct_ptr() rimuovono il tag prima del controllo dell'intervalloun puntatore con tag letto dalla memoria del kernel altrimenti viene rifiutato come non-in-linear-map (direct-entry-fatal reason=bad-task-or-cpu)
src/kernelsnitch/kernelsnitch.hsweep dei tag < 15 → < 16il tag 0xf è il puntatore senza tag/match-all, quindi lo sweep ora copre anche un kernel senza MTE — mte_enabled=1 è sicuro in entrambi i casi
RepositoryRuolo qui
https://github.com/MobiusM/CVE-2026-43499PoC / trigger di crash originale di CVE-2026-43499
https://github.com/x-spy/CVE-2026-43499-popsicleBase di questo port. Xiaomi 17 Pro Max (popsicle), kernel 6.12.23-android16-5; source/ e tools/generate_target.py vengono da qui
https://github.com/Kananosa/CVE-2026-43499-For-Xiaomi-17T-chagallDispositivo sibling più vicino (Xiaomi 17T, chagall, anch'esso MediaTek). Derivato da popsicle, include un preload.so precompilato — le sue costanti compilate hanno confermato l'offset del caricamento fisico
https://github.com/MiCode/Xiaomi_Kernel_OpenSourceSorgenti del kernel Xiaomi, per il cross-check del layout delle struct