
استغلال محلي لجذر النظام لثغرة CVE-2025-21479 (Adreno KGSL) على iQOO Neo8 (SM8475) - قراءة/كتابة الذاكرة الفعلية، تعطيل SELinux، وفتح قشرة جذر (root shell).
كود تجربة رفع الصلاحيات المحلي لـ CVE-2025-21479، والهدف هو Qualcomm Adreno GPU (KGSL) على جهاز vivo V2301A (iQOO Neo8 / PD2301، Snapdragon 8+ Gen 1 / SM8475، Adreno A730، Android 14، نواة GKI 5.10).
من حيث المبدأ، يستغل الثغرة الأمر CP_SMMU_TABLE_UPDATE الخاص بـ KGSL لدفع SMMU الخاص بوحدة معالجة الرسومات،
مما يتيح القدرة على قراءة وكتابة الذاكرة الفيزيائية بشكل عشوائي، ثم تعطيل SELinux وتحديد رموز النواة والحصول على
shell بصلاحيات root — دون الحاجة إلى تفليش الجهاز أو الاعتماد على فتح Bootloader طوال العملية.
البحث الأمني مقتصر فقط على الأجهزة التي تملكها أو التي لديك إذن بها.
and $12, 0x3) على خلل، يجعلها تصنّف حزمة Self-Draw-State (SDS) خطأً على أنها
RingBuffer (RB). لذلك، فإن إرسال CP_SMMU_TABLE_UPDATE مزوّر من وضع المستخدم داخل كتلة SDS
يتيح الكتابة فوق TTBR0 الخاص بـ GPU، مما يجعل جدول صفحات GPU يشير إلى أي صفحة فيزيائية — ومنذ ذلك الحين يستطيع GPU
قراءة وكتابة أي ذاكرة فيزيائية.stabilize_rw يتم تحصين التعيين إلى منطقة ذاتية التعيين بحجم 2 MB،
مما يدعم قراءات سريعة بكميات كبيرة (fast_pread_bytes وغيرها).selinux_state.enforcing في الذاكرة الفيزيائية.
ثم تفريغ صورة النواة من العنوان الفيزيائي الأساسي الثابت 0xA8000000 (الحد الأقصى الافتراضي 43 MB) —
إذ لا يوجد KASLR فيزيائي على SM8475 — وتحليل بنية kallsyms مباشرةً من التفريغ الخام
(مع التعرف التلقائي على ترتيب البايتات)، لذا لا يؤثر KASLR الافتراضي أيضاً.__do_sys_capset باستخدام شيفرة shellcode من نوع AArch64 (prepare_kernel_cred(0) →
commit_creds()، مع تعطيل seccomp). تستدعي العملية الفرعية المتشعبة
capset() → فتصبح uid 0 → ثم تستعيد شيفرة النواة التي جرى الكتابة فوقها → وتعيد العملية الفرعية تنفيذ الأمر الذي تحدده
في نطاق u:r:shell:s0 (الافتراضي sh). في النهاية تصبح شيفرة النواة
مطابقة بايتاً ببايت لما كانت عليه قبل التشغيل.| الطراز | vivo V2301A (iQOO Neo8، الاسم الرمزي PD2301، اللوحة الأم taro) |
| SoC | SM8475 (Snapdragon 8+ Gen 1) + Adreno 730 |
| Android | 14 (UP1A.231005.007، SDK 34، qssi-user) |
| النواة | 5.10.198-gki-gfb2f5774872c |
| SELinux | Enforcing (يتم إيقافه بواسطة هذه الأداة أثناء التشغيل) |
للاطلاع على معلومات الجهاز الكاملة راجع device_info.txt.
├── source/
│ ├── cheese.c # 漏洞利用主程序(include 了下面两个文件)
│ ├── kallsyms_lookup.c # 针对原始内核映像的 kallsyms 解析器
│ └── adrenaline.h # KGSL ioctl / 命令定义(作者 hawkes)
├── exploit # 预编译 arm64 二进制(动态链接,minSdk 21,
│ # NDK r30-beta2)
├── device_info.txt # 用于调参的目标设备信息
└── README.md
ملاحظة: يقوم cheese.c بتضمين kallsyms_lookup.c و adrenaline.h عبر #include،
ويجب وضع الملفات الثلاثة في المجلد نفسه عند الترجمة.
أي إصدار حديث نسبيًا من Android NDK (r25+) مناسب، مثال:
# 静态链接(自包含、任意 API 等级可运行;体积较大)
aarch64-linux-android34-clang -o cheese source/cheese.c -static
# 动态链接(体积小,依赖设备自带的 libc;API 等级需匹配设备)
aarch64-linux-android34-clang -o exploit_dyn source/cheese.c
# 若要兼容 API 21+ 设备,请改用 aarch64-linux-android21-clang
#推送exploit
adb push exploit /data/local/tmp/
#运行exploit
adb shell
chmod +x /data/local/tmp/exploit
/data/local/tmp/exploit
التutorial المفصل اضغط هنا (يحتوي على أداة بنقرة واحدة)
بعد النجاح ستحصل على shell بـ uid=0، وSELinux في هذه الجلسة يكون قد تم تعطيله. بعد إتمام
الاستيلاء على الصلاحيات، تعيد العملية تنفيذ argv[1..] (الافتراضي هو sh). في كل تشغيل توجد فترة عد تنازلي
("pte wait 3 second") وتقدم قراءة نواة بحجم 43 MB ("Read X / 43 MB").

| المتغير | الوظيفة |
|---|---|
CHEESE_PHYADDR=<phys> | فرض تحديد العنوان الفيزيائي الأساسي للنواة (تجاوز جدول الاستكشاف المدمج gPhyAddrs). |
CHEESE_ATTEMPT=<n> | استخدام gPhyAddrs[n] بدلاً من gPhyAddrs[0]؛ بعد فشل تهيئة GPU يقوم maybe_retry بزيادة المحاولة وإعادة المحاولة تلقائياً. |
CHEESE_SWAPPER_PG_DIR_OFF=<off> | تجاوز مسح swapper_pg_dir واستخدام هذا الإزاحة المطلقة مباشرة. |
CHEESE_READ_FULL_KERNEL=1 | قراءة صورة النواة الكاملة (الحد الافتراضي للقراءة هو DEFAULT_KERNEL_SIZE_MB = 43 MB). |
CHEESE_KALLSYMS_MAX_MB=<MB> | تجاوز الحد الأقصى لقراءة kallsyms. |
CHEESE_FORCE_MANUAL_PATCHFINDER=1 | فرض استخدام patchfinder اليدوي كخيار احتياطي (init_cred، prepare_kernel_cred). |
CHEESE_SKIP_GPU=1 | تجاوز مرحلة القراءة والكتابة عبر GPU (لأغراض التصحيح فقط). |
CHEESE_NO_RETRY=1 | الخروج مباشرة بعد الفشل دون إعادة المحاولة برقم آخر. |
بسبب الآلية الخاصة لأجهزة vivo، على iQOO Neo8 يلزم تعطيله للحفاظ على استقرار صلاحيات root (لن يُشرح المبدأ التفصيلي هنا. قد لا يكون هذا قابلاً للتطبيق على أجهزة vivo الأخرى وإصدارات النواة المختلفة، ويلزم استخراج vr.ko وتحليله عكسياً بنفسك). عند تنفيذ العمليات التالية تأكد أولاً من أن جلسة shell الحالية قد حصلت على صلاحيات root.
#备份原始apanic
dd if="$(readlink -f /dev/block/by-name/apanic)" of=/sdcard/apanic_full.bin
#adb shell内执行
adb pull /sdcard/apanic_full.bin ./
#主机端执行
#禁用vr.ko(风险自行评估)
printf '\370\037\000\000\000\000\000\000\000\000\000\000' | dd of=$(readlink -f /dev/block/by-name/apanic) bs=1 seek=$(( $(blockdev --getsize64 /dev/block/by-name/apanic) - 65472 )) conv=notrunc && sync
بعد ذلك، إذا أدى إعادة التشغيل البارد للهاتف إلى فقدان صلاحيات root، فما عليك سوى إعادة تشغيل exploit ثم تنفيذ كسر الحماية
$(find /data/app -type f -name "libksud.so" | grep resukisu) late-load --kmi android12-5.10
توجد الثوابت الخاصة بالجهاز في أعلى source/cheese.c:
KERNEL_PHYS_BASE — العنوان الفيزيائي الأساسي للنواة (الافتراضي 0xA8000000، SM8475)IDMAP_PG_DIR_OFFSET — إزاحة idmap_pg_dir (الافتراضي 0x245a000)selinux_state_offset — الإزاحة المستخدمة لتحديد موقع selinux_state (الافتراضي
0x729030، العنوان الفيزيائي الفعلي = العنوان الفيزيائي لـ idmap_pg_dir + هذه الإزاحة)gPhyAddrs[] — العناوين الفيزيائية الأساسية المرشحة التي تُجرَّب بالتتابعDEFAULT_KERNEL_SIZE_MB — القيمة الاحتياطية / الحد الأعلى لقراءة النواةالمتطلبات المسبقة: GPU من سلسلة Adreno A730/A7xx (البرامج الثابتة المتأثرة) ونظام جهاز لم تُثبَّت عليه رقعة الأمان التي أصدرتها Qualcomm في يونيو 2025، ونواة يمكن تحليل kallsyms منها في التفريغ الفيزيائي، وبدون KASLR فيزيائي.
can't get GPU r/w — فشل تهيئة GPU؛ انتظر أولاً، وإن لم ينجح فجرّب CHEESE_ATTEMPT=1..n أو حدِّد
CHEESE_PHYADDR يدويًا؛ ولتصحيح محاولة واحدة أضف CHEESE_NO_RETRY=1.CHEESE_READ_FULL_KERNEL=1 (مع
توسيع الحد الأعلى عبر CHEESE_KALLSYMS_MAX_MB)، ثم فكِّر في CHEESE_FORCE_MANUAL_PATCHFINDER=1.cheese مفتوح المصدر
الذي تعتمد عليه هذه الأداةadrenaline.h من عام 2020، الذي يوفّر تعريفات واجهة ioctl