
تحليل متعمق وإثبات مفهوم لـ CVE-2026-27280، وهو كتابة خارج الحدود في dng_render_task::ProcessArea الخاص بـ Adobe DNG SDK، يمكن الوصول إليه عبر واجهة برمجة تطبيقات فك ترميز الصور في Android، مع تحليل السبب الجذري، وتقييم قابلية الاستغلال، وتحليل فجوة تنفيذ التعليمات البرمجية عن بُعد (RCE).
dng_render_task::ProcessArea (Adobe DNG SDK / Android)يتم الوصول إليها من ملف DNG عادي عبر واجهة فك ترميز الصور العامة في Android، وتم
إعادة إنتاجها على Galaxy S25 باستخدام /system/lib64/libdng_sdk.so الخاص بالهاتف نفسه.
DNG_REQUIRE(srcArea.Size() == dstArea.Size()) + فهرسة srcArea)#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 <-- عرضة للخطر
يقوم ProcessArea بتعيين مخزن مؤقت مؤقت بحجم البلاطة فوق srcArea لكنه يفهرسه بإحداثيات dstArea.
وبما أن srcArea = dstArea + fSrcOffset و fSrcOffset هو DefaultCropOrigin الخاص بالملف —
وهو غير صفري في كل ملف DNG حقيقي من الكاميرات — فإن مؤشر الوجهة يُزاح خارج نطاق التخصيص بمقدار
fSrcOffset * rowStep * pixelSize، وتتم كتابة قراءة القناع هناك. إنها إزاحة، وليست تجاوز عدد صحيح،
لذا لا تتطلب تخصيصًا ضخمًا: لهذا السبب يمكن الوصول إليها على الهاتف.
01-vulnerability/ الإصدارات المعرضة للخطر والمُصلَحة من dng_render.cpp، وفرق 2471->2502
02-poc/ المولّدات، المُحمّلات، المجسّات (المصادر) + ملفات arm64 الثنائية المجمّعة مسبقًا
03-samples/ ملفات DNG
04-evidence/ سجلات ASAN، tombstones الجهاز، مخرجات المجسّات
05-analysis/ السبب الجذري، المولّد، قياسات الجيران، تحليل فجوة RCE
العمل الذي يتجاوز الحكم السابق: يدحض اثنين من ادعاءاته بالقياس،
يُغلق فجوة "هل يُستخدم مؤشر تالف"، ويحدد بدقة لماذا تتوقف السلسلة.
اقرأ 06-rce-lab/README.md أولاً؛ ملفات evidence/*.md هي
التوثيقات لكل تجربة، و src/ + apk/ هي الأدوات القابلة لإعادة الإنتاج.
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
إعادة بناء مُحمّلات arm64 تتطلب أعلام dng_sdk الخاصة بـ Android (من Android.bp)، وإلا
فلن تتطابق تخطيطات البنى مع المكتبة المثبتة على الجهاز:
-DUNIX_ENV=1 -DqDNGBigEndian=0 -DqDNGThreadSafe=1 -DqDNGUseLibJPEG=1 \
-DqDNGUseXMP=0 -DqDNGValidateTarget=1 -DqDNGUsingSanitizer=1 -DqLinux=1 -DqAndroid=1
هذا يقابل CVE-2026-27280 (DNG SDK 1.7.1 2471 والإصدارات الأقدم، CWE-787، CVSS 3.1 7.8 HIGH)، نُشر في 2026-03-10 — مطابق حسب نطاق الإصدار والفئة، غير مؤكد بتسمية Adobe للدالة.
مُثبت، على مسار فك الترميز الحقيقي في Android، على جهاز مُحدَّث حتى 2026-01-01:
كتابة خارج الحدود بوجهة يختارها المهاجم (بدقة 4 بايت، في كلا الاتجاهين،
مستقلة عن ASLR)؛ يمكن الوصول إليها من ملف DNG عادي عبر AImageDecoder،
تم إثبات إسقاط معرض Samsung في مُحمّل الصور المصغرة؛ تلف صامت وحتمي
للجيران؛ مؤشر تالف يصل إلى free() (تم إغلاق N1)؛
رش كومة معبَّر عنه بصيغة DNG (ImageStats × SubIFD)؛ الكتابة موجهة نحو
تلك الكائنات المرشوشة، 6/10 مقابل 0/10.
ليست RCE، على مسار Android، ولسبب جذري واحد: يمكن للكود كتابة قيمة
واحدة، 0x3F800000. كل شيء يتبع من ذلك — الكتابة متصلة (لا خطوة
فوق ترويسات Scudo)، لا توجد صفر للكتابة (لا تلف في الطول/العداد)، والكتابة
الجزئية الحافظة للوسوم لها هدف ثابت واحد بالضبط. قيمة واحدة هي
محاولة واحدة ضد حجز عشوائي بحجم 256 ميجابايت، ولا كمية رش أو تزامن
تضيف محاولات. على SDK لسطح المكتب، المجموعة القابلة للكتابة هي 256 قيمة → 256 محاولة
عبر نطاق ~67 ميجابايت، ولهذا فإن 7.8 صحيحة هناك.
تم التراجع عن الحكم السابق (05-analysis/05-exploitability-verdict.md)،
تم دحضه بالقياس: "لا يقدم مفكك الترميز الحقيقي بدائية رش" و "التداخل
غير قابل للتوجيه من داخل فك ترميز واحد". العائق ليس PAC أو BTI أو
مجاميع Scudo الاختبارية — بل القيمة الواحدة القابلة للكتابة، وهي خاصية للكود
يزيلها إصلاح Adobe 2502 من الجذر بالفهرسة بـ srcArea.
لم يتم بناء أي استغلال عامل، ولا يُنشر أي شيء هنا.
| الملف | وظيفته |
|---|
trigger_natural_croporigin.dng | هندسة طبيعية (DefaultCropOrigin = 8,8)؛ يُسقط AImageDecoder |
benign_reference.dng | نفس الملف مع أصل 0 — يُفك ترميزه بنجاح، يُستخدم لفحص الكومة |
silent_corruption.dng | فئة حجم صغيرة: يكتب خارج الحدود دون تعطل (5/5) |
far_write_crash.dng | إزاحة كبيرة: يتعطل بشكل مرئي |
| الملف | المحتويات |
|---|
01-root-cause.md | الخلل، الإصلاح، شكل الكتابة |
02-dng-generator.md | كيفية بناء ملف التشغيل، مقبضا الضبط، المزالق |
03-neighbours.md | أرقام التحكم، ما يجاور المخزن المؤقت، التخفيفات |
04-what-is-missing-for-rce.md | ما تم إثباته (P1-P8)، ما لم يُثبت (N1-N3)، الخطوات المتبقية |
05-exploitability-verdict.md | الحكم السابق — تم تجاوزه بواسطة 06-rce-lab، محفوظ للتوثيق |
| الملف | المحتويات |
|---|
EXP1-stride-vs-scudo.md | الخطوة مقابل ترويسات Scudo: ممكنة نظريًا، مستحيلة على مسار Android (planes==1) |
EXP2-N1-corrupted-pointer-used.md | مؤشر تالف يصل إلى free() — تم إغلاق N1 |
EXP2-real-process.md | الكتابة في عملية معرض Samsung الحقيقية، دون زرع أي شيء |
EXP-imagestats-spray.md | رش الكومة الذي وصفه الحكم السابق بالمستحيل، معبَّرًا عنه بصيغة DNG |
EXP-aimed-spray.md | توجيه الكتابة نحو الكائنات المرشوشة: 6/10 مقابل 0/10 |
EXP-small-class-in-app.md | مؤشرات كود في متناول اليد داخل عملية تطبيق حقيقية |
EXP-band-commit.md / EXP-concurrency.md | لماذا يفشل إتمام الهدف: قيمة واحدة قابلة للكتابة = محاولة واحدة |
EXP-write-read-mismatch.md | خلل ثانٍ + التدقيق الكامل لمصدر ProcessArea |
EXP-value-1.0f.md | مسار 1.0f-كقيمة بيانات، مُغلق هيكليًا |