Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-43499-pmg110-root — استغلال تصعيد صلاحيات محلي (LPE) لنظام أندرويد لثغرة CVE-2026-43499 يستهدف OPPO PMG110 (kernel 6.6). يستخدم ثغرة الاستخدام بعد التحرير (UAF) في futex PI للحصول على صلاحيات الجذر وتثبيت خفي su عبر LD_PRELOAD. | Kitploit
أدوات/GitHubGitHub/soralis0912/cve-2026-43499-pmg110-root
أمان أندرويدتصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالما بعد الاستغلالاختبار الاختراقأمن الجوالالفريق الأحمرتطوير الحمولات

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة
استغلال الملفات الثنائية
GitHubsoralis0912/cve-2026-43499-pmg110-root

CVE-2026-43499-pmg110-root

استغلال تصعيد صلاحيات محلي (LPE) لنظام أندرويد لثغرة CVE-2026-43499 يستهدف OPPO PMG110 (kernel 6.6). يستخدم ثغرة الاستخدام بعد التحرير (UAF) في futex PI للحصول على صلاحيات الجذر وتثبيت خفي su عبر LD_PRELOAD.

عرض المستودع
1منذ 24 أياملم تتم المراجعة بعد

pmg110-root

CVE-2026-43499 (futex PI rt_mutex_waiter use-after-free) تصعيد صلاحيات محلي، منقول إلى OPPO PMG110 / K15 Pro+ — MediaTek MT6991، ColorOS 16.

ملف واحد يُدفع، ويُشغَّل عبر LD_PRELOAD:

root@kitploit:~
adb push out/preload-pmg110-16.0.9.400.so /data/local/tmp/preload.so
adb shell chmod 644 /data/local/tmp/preload.so
adb shell LD_PRELOAD=/data/local/tmp/preload.so /system/bin/true

عند النجاح، يُترك su دائم خلفك:

root@kitploit:~
adb shell /data/local/tmp/su -c id      # uid=0(root)

تم التحقق على الجهاز (2026-07-27): uid=0 خلال حوالي 35 ثانية من تشغيل بسيط دون أي تجاوز لمتغيرات البيئة، وكان su يستجيب بعد ذلك من adb shell عادي غير مميَّز:

root@kitploit:~
$ adb shell "/data/local/tmp/su -c 'echo 0 > /proc/sys/kernel/kptr_restrict'"
$ adb shell "/data/local/tmp/su -c 'grep -w init_task /proc/kallsyms'"
ffffffe89033e780 D init_task

تم التحقق من الاستغلال وتثبيت su معًا على هذا الجهاز. وما قرأته تلك الصدفة المُخترَقة لاحقًا يؤكد أيضًا P0_KERNEL_PHYS_LOAD وإزاحات الرموز وKS_MTE_TAGGED=0 بشكل مستقل عن الاستغلال — انظر targets/pmg110-16.0.9.400/NOTES.md.

ما يفعله وما لا يفعله

يشغّل Write 1 (SELinux permissive) وWrite 2 (cred → init_cred)، ويجعل عمليةً فرعية تحصل على uid=0، ومن هناك يثبّت برنامج su الخفي المضمّن.

  • ما زال ملفًا واحدًا يُدفع. su ليس أثرًا ثانيًا: su_daemon.c يُبنى كـ aarch64 PIE مستقل ويُضمَّن عبر .incbin داخل .rodata الخاصة بالمكتبة، فينتقل داخل preload.so ويُكتب مرة أخرى في وقت التشغيل. هذا نهج warhol-root دون تغيير.
  • لا سكربت root، لا ksud، لا KernelSU
  • تبقى العملية المستدعية غير مميَّزة — فهي تحصل على root بسؤال البرنامج الخفي، وهو نفس ما ستفعله من الصدفة لاحقًا
  • يُترك SELinux permissive، كما يتركه warhol-root: يجب على البرنامج الخفي خدمة العملاء غير المميَّزين عبر مقبسه. أعد التشغيل لاستعادة وضع enforcing.

يُثبَّت su في ثلاثة مواضع، لأن أحدها هو الذي ستصل إليه فعلًا:

يستمع البرنامج الخفي على /data/local/tmp/temp_su.sock ويسجّل في /data/local/tmp/su_daemon.log. صلاحيات root لا تدوم عبر إعادة التشغيل — أعد تشغيل سطر LD_PRELOAD بعد كل إقلاع.

لتثبيت KernelSU، استخدم مسار /data/local/tmp/a/e في ghostlock-oneplus بدلًا من ذلك.

العلاقة بـ warhol-root

كل شيء باستثناء نواة الاستغلال هو من warhol-root، مأخوذ لا مُعاد اختراعه:

  • البنية — ملفات رؤوس لكل جهاز تحت targets/<device>/، تُنقل إلى source/src/ وقت البناء، بحيث لا يترك تبديل DEVICE ملفات رأس الجهاز السابق خلفه أبدًا
  • البناء — اختيار سلسلة الأدوات في source/Makefile (NDK إن وُجد، أو clang المضيف مع NDK sysroot إن لم يوجد) وقاعدة التضمين ذات المرحلتين التي تُنتج build/embed/su_daemon_aarch64_pie قبل ربط ملف .so
  • مسار su — su_daemon.c وsu_blob.S مطابقان بايتًا ببايت لملفات warhol-root، وsu_install.c هو مثبّت preload.c الخاص بـ warhol-root

نواة الاستغلال ليست من warhol-root. warhol-root هو popsicle، وهو مقيَّد بـ GKI 6.12 / android16 وتَرفض generate_target.py الخاصة به أي لافتة أخرى. PMG110 يعمل بنواة 6.6 / android15، لذا فالنواة هنا من شجرة ghostlock 6.6 — وهي نفسها سليلة لنفس الشيفرة (kernelsnitch/utils.h وtimeutils.h مطابقان بايتًا ببايت بين المستودعين)، مع مزيد من التطوير.

كل سطر في الاستغلال الفعلي — Write 1، وWrite 2، وKernelSnitch، ومسار pselect — هو نفس الشيفرة في الشجرتين.

من أين يُستدعى تثبيت su

هذا هو الاختلاف البنيوي الوحيد، وهو مفروض لأن الشجرتين تحصلان على root بشكل مختلف.

يمنح warhol-root الصلاحيات لعملية الاستغلال نفسها ولذلك يستدعي install_embedded_su() مباشرة من run_direct_root(). هنا تبدّل Write 2 مؤشر cred لـعملية فرعية مُفترَعة بينما يبقى الأب هو المستدعي غير المميَّز، لذا فالعملية الفرعية في child_main() هي السياق الوحيد القادر على التثبيت — وهناك يعمل.

تحمل الشجرتان نفس كعب install_embedded_su() الضعيف في util.c الذي يعيد ENOSYS؛ وتوفير التعريف القوي هو ما يُفعّل المسار. من الجدير معرفة ذلك لأن بناءً يُسقط su_install.c لسبب ما سيظل يُربط ويُشغَّل — لكنه سيُبلّغ su=0/38 ولن يثبّت شيئًا.

البناء

root@kitploit:~
make                      # = make preload -> out/preload-<DEVICE>.so
make DEVICE=<name>        # use targets/<name>/
make devices              # list available DEVICE values
make info                 # show the selected target and the resolved toolchain

يتم اكتشاف سلسلة الأدوات تلقائيًا: ANDROID_NDK_HOME / ANDROID_NDK_ROOT أولًا، ثم مواقع تثبيت NDK المعتادة على Linux وmacOS، وإن فشلت جميعها، يُستخدم clang المضيف مستهدفًا NDK sysroot. اضبط ANDROID_NDK_HOME فقط لتجاوز البحث. يطبع make info ما اختاره.

يتكون البناء من مرحلتين، وهذا هو الجزء الجدير بمعرفته:

  1. su_daemon.c → build/embed/su_daemon_aarch64_pie, وهو aarch64 PIE مستقل
  2. su_blob.S يُضمّن ذلك الملف الثنائي في .rodata عبر .incbin، ويُربط كل ذلك في ملف preload.so الواحد

إذن make clean وإعادة البناء هما الطريقة الوحيدة لتغيير su المضمّن — يكفي تعديل su_daemon.c وحده، فالاعتماد مُعلَن، لكن الكتلة (blob) أثر بناء وغير متتبَّعة.

تتم إعادة نقل targets/<device>/{target.h,device_offsets.h} إلى source/src/ في كل بناء، لذا لا يمكن أن يُلتقط ملف رأس قديم من جهاز آخر دون أن يُلاحَظ.

out/*.so غير متتبَّع (نفس الاتفاقية المتبعة في warhol-root) — استنسِخ ثم نفّذ make.

يُبنى ملف .so باستخدام -fvisibility=hidden ويُصدّر صفر رموز. رموز مكتبة LD_PRELOAD تفوز في البحث عن الرموز للعملية بأكملها، لذا فإن أي رمز تُصدّره قد يحجب رمزًا بنفس الاسم في الملف الثنائي المضيف أو في libc. هذا العلم يتحكم في توليد شيفرة C فقط، لذا يعلّم su_blob.S رمزَيه .hidden يدويًا — وبدون هذين السطرين كانت حدود الكتلة ستكون الشيء الوحيد الذي ما تزال المكتبة تُصدّره.

متغيرات البيئة

لم يكن أيٌّ من هذه ضروريًا في التشغيل المُتحقَّق منه.

قراءة السجل

root@kitploit:~
[*] futex_hashsize 2048 (8 possible CPUs)
[*] ks collisions=3/3 baseline=8 threshold=10x (80) accepted=[1244..1597] slowest_rejected=N
[+] child uid = 0
[+] embedded su wrote 15304 bytes to /apex/com.android.virt/bin/su
[+] embedded su daemon ready pid=NNNN socket=/data/local/tmp/temp_su.sock daemon=/apex/com.android.virt/bin/su
[+] embedded su install ok=1 errno=0 daemon=NNNN
[+] su ready: /data/local/tmp/su and /apex/com.android.virt/bin/su
[+] ghostlock preload verdict: EXPLOIT OK

child uid = 0 تعني نجاح الاستغلال؛ وكل ما بعدها هو التثبيت. يُبلَّغ الاثنان منفصلين عمدًا، وكذلك الحكم:

الحالة الوسطى هي التمييز الجدير بالاهتمام: فهي تقول إن الإزاحات في target.h صحيحة لهذا البناء وإن المشكلة في مكان ما في التثبيت، وهو أمر مختلف تمامًا عند التنقيح. su=0/38 (ENOSYS) داخلها تعني تحديدًا أن الكعب الضعيف هو ما تم ربطه.

mm_struct leak failed متبوعًا بـ prepare_kernel_page retry N/24 ليس فشلًا. إنه تقدم الحلقة، والتشغيل الناجح يُظهره أيضًا. لم يفشل شيء حتى تُستنفد 24 محاولة ويظهر prepare_kernel_page timeout. وبالمثل، فإن probing cfi ... expected=9 مع child uid = 2000 هي جولة واحدة ناقصة من أصل عشر.

لا تحكم على تشغيل من سجل مبتور — هذا الخطأ كلّف جولة كاملة من التشخيص الخاطئ هنا.

التشغيل الفاشل بالكامل أمر طبيعي أيضًا. سباق pselect ليس مضمونًا 100%: يمكن أن يخسره تشغيل خمس مرات متتالية وينتهي بـ Write 1 failed، ثم يربحه التشغيل التالي من المحاولة الأولى مع ret=9. لوحظ هذا على هذا الجهاز. ret=4 expected=9 هو شكل خسارة السباق، وليس target.h خاطئًا — فشل واحد ليس سببًا لإعادة اشتقاق الإزاحات. أعد تشغيله.

الملفات

الترخيص

لأغراض البحث الأمني المصرَّح به والتعليم فقط.

تنزيل الأداة
الجهازOPPO PMG110 / K15 Pro+ / OP61E5L1
SoCMediaTek MT6991 (Dimensity 9500s)
النواة6.6.118-android15-8-g93e223c276e7-abogki500782043-4k (GKI, 4K pages)
الإصدارColorOS 16 / PMG110_16.0.9.400(CN01) — نفس بايتات النواة في 16.0.8.300
الثغرةCVE-2026-43499، غير مُصلَحة في هذه الصورة (كما يظهر من التفكيك، وليس من رقم الإصدار)
المسارالسبب
/apex/com.android.virt/bin/suعلى tmpfs مُثبَّت فوق هذا الدليل؛ وهو في PATH لصدفة root
/data/local/tmp/suيمكن الوصول إليه من adb shell عادي دون حيل PATH
/apex/com.android.virt/bin/su في مساحة أسماء التركيب الخاصة بـ adbdيُثبَّت عبر setns، لذا فسيراه أي adb shell جديد
الملفالعلاقة
util.c slide.c fops.c pipe.c root.c miniadb.c common.h offset.h kernelsnitch/*من ghostlock، مطابق بايتًا ببايت
su_daemon.c su_blob.Sمن warhol-root، مطابق بايتًا ببايت (يضيف su_blob.S سطرَي .hidden — انظر البناء)
su_install.cمثبّت preload.c الخاص بـ warhol-root، نُقل إلى ملف خاص به لأن preload.c في هذه الشجرة لديه مهمة أخرى أصلًا
main.cمن ghostlock، مع استدعاء su في العملية الفرعية المُخترَقة وإبلاغ النتيجة
preload.cموجود هنا فقط — المُنشئ وسجل الوجهتين
offsets.hتعريف البنية فقط؛ الإدخال يُنقل من targets/<device>/device_offsets.h
المتغيرالتأثير
GHOSTLOCK_LOGوجهة التسجيل (الافتراضي /data/local/tmp/.ghostlock.log)؛ الإخراج يذهب إلى stdout و الملف
GHOSTLOCK_KS_VERBOSE=1طباعة عناوين التصادم ونطاقات المسح الخاصة بـ KernelSnitch
GHOSTLOCK_KS_THRESHOLD=<n>تجاوز مضاعِف عتبة التصادم
GHOSTLOCK_MTE=1مسح وسوم مؤشرات النواة أيضًا (أبطأ 15 مرة)
GHOSTLOCK_PHYS_LOAD=0x...تجاوز عنوان التحميل الفيزيائي للنواة
PSELECT_SHIFT=<n>تجاوز إزاحة تراكب المكدس (يستبدل، ولا يضيف)
الحكمالمعنى
EXPLOIT OKroot، وsu يستجيب
EXPLOIT OK, SU INSTALL FAILEDنجح Write 1 وWrite 2؛ التثبيت فقط هو ما أخطأ
EXPLOIT FAILEDلم تنجح عمليات الكتابة
ABORTEDانتهى التشغيل قبل أن يتمكن من الإبلاغ — اقرأ آخر سطر [!]
المسارالمحتويات
source/src/preload.cالمُنشئ: يشغّل الاستغلال، يُبلّغ، يتوقف
source/src/main.cالاستغلال نفسه (Write 1 / Write 2)
source/src/su_daemon.cملف su الثنائي — يُبنى مستقلًا كـ aarch64 PIE، غير مرتبط داخل .so
source/src/su_blob.Sيُضمّن ذلك الـ PIE عبر .incbin داخل .rodata الخاصة بملف .so
source/src/su_install.cيكتب الكتلة مرة أخرى، يبدأ البرنامج الخفي، يختبره
source/src/target.hوجهة النقل (مستثناة من تتبع git)
targets/<device>/target.hتخطيط زمن الترجمة: إزاحات البنيات، ثوابت physmap، أشكال slab وfutex
targets/<device>/device_offsets.hإزاحات الرموز العامة من kallsyms
tools/extract_device.pyboot.img → الإزاحات، وحقول بنيات BTF، ونتيجة تراكب pselect
tools/preloader_memlayout.pyMediaTek preloader → P0_KERNEL_PHYS_LOAD
tools/qemu_verify.pyيُقلع النواة تحت QEMU: يقيس تراكب المكدس، ويتحقق من ثبات الخريطة الخطية
tools/device_probe.shفحص مسبق من adb shell غير مميَّز