
# Chaîne d'exploitation complète pour Android Chromium combinant la fuite d'informations CVE-2026-11057 et l'use-after-free CVE-2026-5281 pour réaliser un détournement de vtable et une exécution de code arbitraire.
Pixel 7 Android 16 ARM64
commit 994c846bbd7a35241ba7c08158c13d66412a6993 (HEAD -> 146.0.7680.111, tag: 146.0.7680.111)
Author: Roger McFarlane <[email protected]>
Date: Mon Mar 9 12:48:07 2026 -0700
Ce dépôt combine CVE-2026-11057 (mémoire d'image de glyphe non initialisée dans Skia) et CVE-2026-5281 (use-after-free de DeviceInfo dans le serveur wire de Dawn) en une chaîne complète. Toutes les modifications sont côté renderer ; le code du processus GPU reste inchangé :
Fuite d'informations (CVE-2026-11057) — Déclencher un tampon d'image de glyphe non initialisé via le rendu de texte sur canvas, relire les pointeurs du tas du processus GPU, les valider par des séries arithmétiques, dériver la base du pool PartitionAlloc, et calculer la cible factice du Server M = POOL + 0x202A08000 (offset calibré).
Spray CC — createBuffer(label="CCM:<m>:<n>") déclenche l'injection de 3000 ChunkedCommands incomplètes (bucket 10KB, remainingSize=1, maintenues en vie dans mChunkedCommands du serveur wire). La charge utile remplit la région autour de M avec un faux Server agencé pour Android arm64 : vptr MutexProtected à +0xB20, ChunkedCommandSerializer à +0xB50/+0xB58, faux CommandSerializer/vtable à +0xC00/+0xD00.
Déclenchement de 5281 + occupation — queue.writeBuffer(buffer, 0x414141, ...) appelle d'abord Unregister(Device) pour libérer le DeviceInfo de 16 octets, puis injecte une ChunkedCommand d'occupation de 16 octets pour récupérer cet emplacement et écraser info->server par M, et enfin déclenche une erreur de validation avec un offset hors limites.
Callback pendant → détournement de vtable — Le callback d'erreur non capturée déréférence info->server = M (faux Server) : les mutex remis à zéro passent, l'exécution atteint OnUncapturedError → SerializeCommand, et l'appel indirect via vtable relative atteint notre fausse vtable, donnant pc = fake_vtable + offset int32 contrôlé, démontré par pc = 0x7641414141.
Remarque : Chromium sur Android arm64 utilise des vtables relatives (
-fexperimental-relative-c++-abi-vtables) ; les entrées de vtable sont des offsets relatifs sur 32 bits plutôt que des pointeurs de fonction absolus, c'est pourquoi le PoC utilise un offset int32 contrôlé comme marqueur au point de détournement de vtable.
Sur l'appareil de test, la chaîne complète atteint le crash par détournement de vtable avec un taux de réussite proche de 100 % ; l'étape de fuite peut occasionnellement nécessiter plusieurs rechargements automatiques avant de réussir.
SkStrike.cpp.patch — Déclencheur de fuite CVE-2026-11057. FlattenGlyphsByType() réécrit la charge utile de strike afin que le processus GPU crée un SkGlyph avec fImage == nullptr, finissant par lire un tampon d'image non initialisé pour fuiter des pointeurs du tas.Device.cpp.patch — Spray CC du client wire de Dawn. APICreateBuffer() analyse le label CCM:, construit la charge utile du faux Server Android arm64, et injecte N ChunkedCommands incomplètes qui restent en vie dans le processus GPU.ApiProcs.cpp.patch — Déclenchement de CVE-2026-5281 + occupation. Sur l'offset magique 0x414141 de QueueWriteBuffer, il appelle Unregister(Device) pour libérer DeviceInfo, injecte une ChunkedCommand de 16 octets pour récupérer l'emplacement et définir info->server = M, puis poursuit avec un offset hors limites pour déclencher le callback pendant.exploit.html — Orchestration de la page : primitive de fuite (groom/draw/readCell/verifyRuns/derivePoolBase), spray CC, et un déclencheur autonome exploit5281() ; en cas d'échec, il nettoie l'état du spray et recharge afin que les étapes n'interfèrent pas entre elles.Cet ExP n'est divulgué que jusqu'à l'étape de détournement de vtable (cible d'appel indirect contrôlée, pc = base+0x41414141). Les étapes à partir du saut contrôlé, ainsi que l'implémentation de la RCE, restent confidentielles et ne sont pas incluses dans ce dépôt.
Mon exploit diffère de l'approche du rapporteur original sur un point clé. L'exploit original était obtenu en modifiant le code source de PartitionAlloc dans le processus GPU pour désactiver la randomisation d'adresses. Cette approche ne convient qu'à des fins de preuve de concept. En revanche, mon exploit combine une vulnérabilité de divulgation d'informations pour contourner la randomisation d'adresses, permettant un exploit pleinement fonctionnel qui opère dans des environnements réels.
# Set build arguments here. See `gn help buildargs`.
is_official_build = true
is_debug = false
symbol_level = 0
v8_symbol_level = 0
blink_symbol_level = 0
is_component_build = false
proprietary_codecs = true
ffmpeg_branding = "Chrome"
dcheck_always_on =false
optimize_webui = true
android_static_analysis = "off"
target_os = "android"
target_cpu = "arm64"
# Disable PartitionAllocEventuallyZeroFreedMemory
disable_fieldtrial_testing_config = true
treat_warnings_as_errors = false
adb logcat | grep DEBUG sur le PC