Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-27280 — In-depth analysis and proof-of-concept for CVE-2026-27280, an out-of-bounds write in Adobe DNG SDK's dng_render_task::ProcessArea, reachable via Android's image decoding API, with root cause, exploitability assessment, and RCE gap analysis. | Kitploit
Tools/GitHubGitHub/r3n3r0/cve-2026-27280
Android SecurityVulnerability AnalysisExploitationReverse EngineeringFuzzingMobile SecurityPapers & ResearchBinary Exploitation
GitHubr3n3r0/cve-2026-27280

CVE-2026-27280

In-depth analysis and proof-of-concept for CVE-2026-27280, an out-of-bounds write in Adobe DNG SDK's dng_render_task::ProcessArea, reachable via Android's image decoding API, with root cause, exploitability assessment, and RCE gap analysis.

1271 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

Out-of-bounds write in dng_render_task::ProcessArea (Adobe DNG SDK / Android)

Reached from an ordinary DNG file through Android's public image-decoding API, and reproduced on a Galaxy S25 using the phone's own /system/lib64/libdng_sdk.so.

  • Vulnerable: DNG SDK 1.7.1 build 2410 / 2471 (2410 is what the tested device ships)
  • Fixed: build 2502 (DNG_REQUIRE(srcArea.Size() == dstArea.Size()) + srcArea indexing)
  • Device: SM-S931B, Android 16, security patch 2026-01-01 — pre-fix, confirmed by the absence of the 2502 guard string in the shipped library
#12 AImageDecoder_decodeImage                  /system/lib64/libjnigraphics.so
#11 android::ImageDecoder::decode              /system/lib64/libhwui.so
#09 SkCodec::getPixels                         /system/lib64/libhwui.so
#08 SkRawCodec::onGetPixels                    /system/lib64/libhwui.so
#07 dng_render::Render()                       /system/lib64/libdng_sdk.so
#06 SkDngHost::PerformAreaTask                 /system/lib64/libhwui.so
#00 dng_render_task::ProcessArea               /system/lib64/libdng_sdk.so   <-- vulnerable

One-paragraph summary

ProcessArea maps a tile-sized temporary buffer over srcArea but indexes it with dstArea coordinates. Since srcArea = dstArea + fSrcOffset and fSrcOffset is the file's DefaultCropOrigin — non-zero in every real camera DNG — the destination pointer is displaced out of the allocation by fSrcOffset * rowStep * pixelSize, and the mask read-back writes there. It is a displacement, not an integer overflow, so it needs no huge allocation: that is why it is reachable on a phone.

Layout

01-vulnerability/   the vulnerable and fixed versions of dng_render.cpp, and the 2471->2502 diff
02-poc/             generators, loaders, probes (sources) + prebuilt arm64 binaries
03-samples/         the DNG files
04-evidence/        ASAN logs, device tombstones, probe output
05-analysis/        root cause, generator, neighbour measurements, RCE gap analysis

03-samples

filewhat it does
trigger_natural_croporigin.dngnatural geometry (DefaultCropOrigin = 8,8); crashes AImageDecoder
benign_reference.dngsame file with origin 0 — decodes fine, used to probe the heap
silent_corruption.dngsmall size class: writes out of bounds without crashing (5/5)
far_write_crash.dnglarge displacement: faults visibly

05-analysis

filecontents
01-root-cause.mdthe bug, the fix, the shape of the write
02-dng-generator.mdhow the trigger file is built, the two tuning knobs, pitfalls
03-neighbours.mdcontrollability numbers, what sits next to the buffer, mitigations
04-what-is-missing-for-rce.mdwhat is proven (P1-P8), what is not (N1-N3), the remaining steps
05-exploitability-verdict.mdthe earlier verdict — superseded by 06-rce-lab, kept for the record

06-rce-lab (the RCE push)

The work that goes beyond the earlier verdict: it disproves two of its claims by measurement, closes the "is a corrupted pointer used" gap, and pins exactly why the chain stops. Read 06-rce-lab/README.md first; the evidence/*.md files are the per-experiment write-ups, and src/ + apk/ are the reproducible harnesses.

filecontents
EXP1-stride-vs-scudo.mdstride vs Scudo headers: possible in the abstract, impossible on the Android path (planes==1)
EXP2-N1-corrupted-pointer-used.mda corrupted pointer reaches free() — N1 closed
EXP2-real-process.mdthe write in the real Samsung Gallery process, nothing planted
EXP-imagestats-spray.mdthe heap-spray the earlier verdict called impossible, expressed by the DNG format
EXP-aimed-spray.mdaiming the write onto sprayed objects: 6/10 vs 0/10
EXP-small-class-in-app.mdcode pointers in reach inside a real app process
EXP-band-commit.md / EXP-concurrency.mdwhy committing the target fails: one writable value = one shot
EXP-write-read-mismatch.mda second defect + the full source audit of ProcessArea
EXP-value-1.0f.mdthe 1.0f-as-datum route, closed structurally

Reproduce

adb push 02-poc/bin-arm64/poc_aimg 03-samples/trigger_natural_croporigin.dng /data/local/tmp/
adb shell "cd /data/local/tmp && chmod 755 poc_aimg && ./poc_aimg trigger_natural_croporigin.dng"
# -> Segmentation fault, tombstone frames inside libdng_sdk.so

Rebuilding the arm64 loaders requires Android's own dng_sdk flags (from Android.bp), or the struct layouts will not match the shipped library:

-DUNIX_ENV=1 -DqDNGBigEndian=0 -DqDNGThreadSafe=1 -DqDNGUseLibJPEG=1 \
-DqDNGUseXMP=0 -DqDNGValidateTarget=1 -DqDNGUsingSanitizer=1 -DqLinux=1 -DqAndroid=1

Status

This corresponds to CVE-2026-27280 (DNG SDK 1.7.1 2471 and earlier, CWE-787, CVSS 3.1 7.8 HIGH), published 2026-03-10 — matched by version range and class, not confirmed by Adobe naming the function.

Proven, on the real Android decode path, on a device patched to 2026-01-01: out-of-bounds write with attacker-chosen destination (4-byte granularity, both directions, ASLR-independent); reachable from a plain DNG through AImageDecoder, demonstrated killing the Samsung Gallery in its thumbnail loader; silent deterministic corruption of neighbours; a corrupted pointer reaching free() (N1 closed); a heap-spray expressed by the DNG format (ImageStats × SubIFD); the write aimed onto those sprayed objects, 6/10 vs 0/10.

Not RCE, on the Android path, and for one root reason: the code can write a single value, 0x3F800000. Everything follows from that — the write is contiguous (no stride over Scudo headers), there is no zero to write (no length/refcount corruption), and the tag-preserving partial overwrite has exactly one fixed target offset. One value is one shot against a randomised 256 MB reservation, and no amount of spray volume or concurrency adds shots. On the desktop SDK the writable set is 256 values → 256 shots across a ~67 MB band, which is why the 7.8 is correct there.

Retracted from the earlier verdict (05-analysis/05-exploitability-verdict.md), falsified by measurement: "a real decoder offers no spray primitive" and "the overlap is not steerable from inside a single decode". The block is not PAC, BTI or Scudo's checksums — it is the single writable value, a property of the code that Adobe's 2502 fix removes at the root by indexing with srcArea.

No working exploit was built, and none is published here.

Download Tool