
# أداة تحميل KernelSU عبر adb لهواتف Google Pixel الأصلية: تمكين القراءة/الكتابة المؤقتة للنواة عبر CVE-2026-43499 (GhostLock)، ثم تحميل متأخر لوحدة kernelsu.ko المطابقة للتوقيع للنواة قيد التشغيل (KMI). مستقلة عن أي مدير.
أداة تعمل عبر adb تحوّل هاتف Google Pixel أصلي بقفل bootloader إلى جهاز مُجذَّر عبر KernelSU دون فتح قفل bootloader أو تعديل صورة الإقلاع. من جهاز المضيف، تشغّل استغلال نواة في مساحة المستخدم غير مميَّز على الجهاز للحصول على وصول مؤقت للقراءة/الكتابة على النواة، وتستخدم هذه الأولية لتصحيح بيانات اعتماد الجذر، ثم تُحمّل لاحقًا وحدة نواة KernelSU القابلة للتحميل (kernelsu.ko) في نواة GKI قيد التشغيل وتسلّم التحكم إلى أي مدير KernelSU مثبَّت بالفعل (KernelSU أو KernelSU-Next أو SukiSU أو أي نسخة أخرى). تستهدف هواتف Pixel بنظام Android 17 على نوى GKI 6.1 و6.6 وتدير التدفق بالكامل عبر adb shell لتسلسل حتمي وسجلات زمنية.
الحمولة على الجهاز هي سلسلة LPE كاملة مضمّنة لثغرة CVE-2026-43499 ("GhostLock")، وهي use-after-free في مكدس وراثة الأولوية futex/rtmutex في kernel/locking/rtmutex.c. في مسار التراجع requeue-PI، تمسح remove_waiter() حقل pi_blocked_on على requeuer (current) بدلاً من waiter الفعلي، تاركة مؤشرًا معلّقًا إلى خانة مكدس نواة محرَّرة كانت تحتوي على rt_mutex_waiter. الثغرة قابلة للوصول من عملية عادية غير مميَّزة:
owner وwaiter وconsumer) تبني سلسلة PI؛ يتوقف waiter على FUTEX_WAIT_REQUEUE_PI، ويطلق الخيط الرئيسي FUTEX_CMP_REQUEUE_PI، ويقود sched_setattr من consumer عملية التراجع.pselect()/select() مُتحكَّم بها (أو مسار TCP_ZEROCOPY_RECEIVE على بعض أهداف 6.1) التي تضع كلمات fd_set فوق بنية waiter، كاتبةً rt_mutex_waiter مسطّحًا مزوَّرًا بحيث يمشي المؤشر المعلّق عبر حقول rb-tree وقفل يتحكم بها المهاجم — أولية كتابة مؤشر واحدة مُتحكَّم بها.mm_struct/sk_buff/ المرشوشة.ثم تُصحَّح حالة الجذر وSELinux عبر أولية الأنبوب: تُصفَّر بيانات cred لمهمة الجذر الفرعية إلى uid/gid 0 مع مجموعات قدرات كاملة، وتُعيَّن osid/sid الخاصة بـ SELinux إلى SECINITSID_KERNEL، ويُمسح seccomp، وتُعيَّن selinux_state.enforcing إلى 0.
سلسلة الاستغلال وأوراكل KASLR والقناة الجانبية KernelSnitch مصدرها بحث NebuSec IonStack Part II — GhostLock (PoC NebuSec/CyberMeowfia، رخصة Apache-2.0)، مُكيَّفة هنا لـ Pixel/aarch64. انظر الإسناد والترخيص.
مرحلة واحدة بالضبط من السلسلة يمكن أن تُسبب انهيار النواة: اشتقاق انزياح KASLR، الذي يتسابق على صفحة يأمل أنه استعادها. كل المراحل الأخرى آمنة لإعادة المحاولة، وقاعدة نص النواة ثابتة لعمر إقلاع واحد. يقسّم تدفق المضيف على هذه الخاصية:
KASLR_BASE في بيئتها. تعيد كتابة المؤشر المزوَّر توجيه random_table sysctl ctl_table.data إلى مؤشر نص نواة معروف؛ وقراءة /proc/sys/kernel/random/boot_id تُسرّبه عبر proc_do_uuid()، وطرح إزاحة الصورة يعطي _stext/قاعدة KASLR. restore_slide_boot_id() يصلح ctl_table.data التالف. لأن سباقًا خاسرًا يعيد تشغيل الجهاز، يسبق كل محاولة انتظار للإقلاع ويصنّف فحص الحيوية الاختفاء كأنه انهيار. عند النجاح، يصدر سجل الجهاز slide-kaslr-ok pid=<pid> base=<hex>، وتُثبَّت القاعدة للإقلاع الحالي.KASLR_BASE=0x<base>. هذا المسار لا يسبب انهيارًا أبدًا ويُكرَّر حتى يبلغ id عن uid=0 عبر su المؤقت.يُحل الجهاز المتصل مقابل data/targets.json وقت التشغيل؛ لا شيء مكتوب بثبات للجهاز. يحدث حلّان مستقلان:
uname -r)، إما من إدخال الهدف المطابق أو مشتقة من سلسلة الإصدار (مثل android14-6.1).إعادة استخدام حمولة واحدة عبر أجهزة كثيرة تتبع بنية GKI/KMI. كل جهاز على نفس بناء GKI يشغّل vmlinux متطابقًا بايتًا ببايت، وإزاحات حقول البنى (task_struct->cred وcred->uid، …) مجمَّدة لعمر فرع KMI بموجب عقد نوع KMI وإنفاذ CRC لـ MODVERSIONS. عناوين رموز النواة المطلقة، على النقيض، يقررها الرابط لكل بناء ab<NNN>، لذا إزاحات الاستغلال الثابتة تنتمي إلى vmlinux محدد واحد؛ صور النواة المختلفة تتطلب إذن حمولات مختلفة حتى عندما تتطابق KMI الخاصة بها. data/targets.json يرمّز هذا بالضبط: أجهزة كثيرة تُدمج على حمولة واحدة مفتاحية بصورة النواة، بينما صورة نواة مختلفة تحصل على حمولتها الخاصة.
يتطلب التحميل المتأخر لـ LKM نواة GKI (5.10+) مع دعم وحدات قابلة للتحميل و.ko مطابقًا لـ KMI. تصادق وحدة نواة KernelSU على مديرها بالتحقق داخل النواة من كتلة توقيع v2 لـ APK المدير ومقارنة SHA-256 لشهادة التوقيع مع زوج KSU_EXPECTED_SIZE/KSU_EXPECTED_HASH مضمَّن في .ko. لذلك فإن kernelsu.ko المشحون داخل إصدار مدير وAPK ذلك المدير يتشاركان هوية توقيع واحدة؛ ksud غير متطابق يحمّل السائق لكنه لا يضبط بت تفويض المدير أبدًا، تاركًا الجهاز بلا جذر قابل للاستخدام.
يكرّم التدفق هذا الارتباط: يحل مسار APK المدير المثبَّت (pm path <manager package>)، ويسحب APK، ويستخرج lib/arm64-v8a/libksud.so كملف ksud الثنائي، وإذا لم يكن مدير مثبَّتًا يتوقف. مع الاحتفاظ بالجذر المؤقت، يُجهَّز ذلك ksud كملف تنفيذي مملوك للجذر ويُستدعى كـ ksud late-load --kmi <kmi> --package-name <manager package>. يكتشف التحميل المتأخر KMI الحالية، ويسحب "{kmi}_kernelsu.ko" من أصوله المضمّنة، ويجري إعادة تموضع رموز يدوية (حل كل رمز SHN_UNDEF مقابل /proc/kallsyms، وإعادة كتابة الإدخالات إلى SHN_ABS)، ويستدعي init_module(2) على المخزن المؤقت المُصحَّح. ثم يشغّل بقية خط أنابيب الإقلاع الذي كان init سيشغّله (تثبيت ksud، وrestorecon، وتحميل sepolicy.rule وملفات تعريف الجذر، وتشغيل سكربتات post-fs-data/المراحل، وتركيب تراكب الوحدات).
يتحول التحميل المتأخر إلى خفيّة ويعيد فرض SELinux في طفله المنسوخ، الذي يهدم خفيّة su المؤقتة للاستغلال؛ لذلك يجب ألا يمر التحقق عبر su. بدلاً من ذلك، يُستعلم السائق المحمَّل مباشرة عبر سطح استدعاءات النظام، القابل للوصول من قشرة عادية دون جذر: يُستطلَع ksud debug version ويُحلَّل رقم النواة المُبلَّغ عنه. رقم إصدار غير فارغ وغير صفري يؤكد أن السائق مقيم ويجيب. مسار تثبيت السائق هو آلية سحر reboot(2) ← واصف التثبيت ← KSU_IOCTL_GET_INFO (reboot(0xDEADBEEF, 0xCAFEBABE, 0, &fd) يثبّت واصف [ksu_driver] مجهولًا؛ GET_INFO يعيد {version, flags, features, uapi_version})، مع قناة prctl(0xDEADBEEF, …) القديمة كمسار احتياطي. نفس الفحص عند بدء التشغيل يختصر التدفق كله عندما تكون الوحدة مقيمة بالفعل للإقلاع الحالي.
يجهّز الاستغلال su المؤقت في /apex/com.android.virt/bin/su، على tmpfs مُركَّب فوق دليل apex bin ذلك داخل مساحة أسماء mount الخاصة بـ adbd، لأن ذلك الدليل يسبق /system/bin في PATH لقشرة — لذا su المجردة في adb shell تصل إلى المؤقتة بينما يعمل التدفق. ثم يهدم التحميل المتأخر خفيّة su المؤقتة (انظر (هـ)) دون إزالة الظل، ما يترك adb shell su مجردة تشغّل عميلًا يتيمًا يفشل مع su: connect daemon: Permission denied حتى مع عمل الجذر، ويترك الملفات الثنائية الحقيقية للـ apex (crosvm وvirtmgr وvm، …) مخفية. بمجرد أن يبلغ التحقق عن سائق حي، يفك التدفق تركيب tmpfs المؤقت — عبر /system/bin/su الخاص بـ KernelSU نفسه، لأن خفيّة الاستغلال رحلت بالفعل — ويزيل عميل su المؤقت والمقبس والسجل، ويُبلغ عن أي su تحله الآن adb shell عادية. إنه بأفضل جهد: عند الفشل يحذر بأمر اليدوي بدلاً من إفشال التشغيل، وإعادة الإقلاع تمسح التركيب بغض النظر.
adb على المضيف، مع تفويض الجهاز (تصحيح أخطاء USB مفعّل).kernelsu.ko المضمَّن فيه.artifacts/exploits/ (انظر بناء الحمولات).# جهاز واحد على adb؛ مدير مثبَّت؛ حمولات مبنية.
bin/pixel-ksu-root
يحل السائق الجهاز مقابل data/targets.json، ويشغّل تدفق KASLR على مرحلتين، ويحمّل الوحدة متأخرًا عبر ksud المشتق من المدير، ويتحقق عبر استدعاء نظام السائق. يخرج برمز غير صفري إذا لم تُحل حمولة للجهاز، أو إذا لم يكن مدير مثبَّتًا، أو إذا لم يبلغ التحقق أبدًا عن سائق حي.
KASLR_BASE=0x<hex> — يُمرَّر إلى حمولة الجهاز أثناء المرحلة ب لإعادة التشغيل ضد قاعدة ثابتة مشتقة مسبقًا لكل إقلاع. غير معيَّن أثناء المرحلة أ حتى تشتق الحمولة القاعدة بنفسها.ANDROID_NDK_HOME — مسار Android NDK، مطلوب فقط عند بناء الحمولات.API — مستوى API لنظام Android لأداة NDK عند بناء الحمولات (الافتراضي 35).pixel-ksu-root/
├── bin/ نقطة دخول سائق المضيف (تدفق مدفوع بـ adb)
├── data/
│ └── targets.json جدول حل الجهاز→الحمولة والجهاز→KMI
├── exploit/ مصدر حمولة CVE-2026-43499 المضمّنة
│ ├── Makefile بناء aarch64 NDK لكل هدف
│ ├── src/ مجموعة المصدر الأساسية android15-6.6
│ │ ├── main.c slide.c fops.c pipe.c root.c preload.c util.c
│ │ ├── su_daemon.c مساعد su المؤقت الذي تولده السلسلة
│ │ ├── kernelsnitch/ رؤوس القناة الجانبية لاحتلال تجزئة futex
│ │ └── targets/ target.h لكل جهاز+بناء (إزاحات النواة)
│ └── src/61/ مجموعة مصدر android14-6.1 (slide61.c، مسار TCP)
├── lib/ دوال shell/مساعد مشتركة في المضيف
├── scripts/
│ └── build-payloads.sh يبني ويزيل تكرار مجموعة الحمولات
├── artifacts/
│ └── exploits/ ملفات .so الحمولات المبنية والمُدمجة
└── docs/ ملاحظات التصميم والتحليل
scripts/build-payloads.sh يغلّف exploit/Makefile لكل هدف ويصدر مجموعة الحمولات المُدمجة المسماة في data/targets.json إلى artifacts/exploits/. يبني .so واحدًا لكل مجموعة إزاحات فريدة (من هدف build_from لتلك المجموعة) بدلاً من واحد لكل جهاز.
export ANDROID_NDK_HOME=/path/to/android-ndk # يجب أن يحتوي على أداة aarch64 NDK
scripts/build-payloads.sh # يبني كل حمولة في data/targets.json
يختار Makefile أداة aarch64 NDK Clang من ANDROID_NDK_HOME ويجمع هدفًا واحدًا في كل مرة؛ API (الافتراضي 35) يختار سائق aarch64-linux-android<API>-clang. تُختار مجموعة المصدر حسب عائلة النواة — أهداف android15-6.6 تجمع الأساس src/، وأهداف android14-6.1 تجمع src/61/ — وإزاحات النواة المطلقة لكل هدف تأتي من src/targets/<codename>-<build>/target.h. لبناء هدف واحد مباشرة:
make -C exploit TARGET=husky-CP2A.260705.006
data/targets.json يسرد 19 إدخال جهاز/بناء تغطي 18 طراز Pixel (يظهر bluejay على بنائين من البرنامج الثابت)، مجمعة في 5 حمولات إزاحات نواة. الاختيار حسب صورة النواة، لذا الأجهزة التي تشارك vmlinux تُدمج على حمولة واحدة؛ صورة نواة مختلفة تحصل على حمولتها الخاصة.
الأجهزة على صورة نواة android14-6.1-a المشتركة (6.1.157-android14-11-gbd23337e42e7-ab14791245) تمتد عبر عائلات Pixel 6/6 Pro/6a و7/7 Pro/7a و8/8 Pro و9/9 Pro/9 Pro XL/9 Pro Fold؛ android14-6.1-b وandroid14-6.1-akita يعزلان طرازات على نفس KMI يختلف بناء نواتها أو إزاحاتها؛ android15-6.6 يغطي عائلة Pixel 10.
NebuSec/CyberMeowfia تحت Apache-2.0؛ الاكتشاف منسوب إلى أدوات VEGA الخاصة بـ NebuSec، أُفصح عنه في 2026-07-07.exploit/ المضمّنة تضيف إزاحات أهداف android14-6.1 وandroid15-6.6 وخفيّة تحميل متأخر لـ KernelSU فوق استغلال NebuSec؛ لا تحمل ترخيصًا منفصلًا وترث شروط Apache-2.0 من المصدر الأعلى.ksud ونموذج تفويض المدير الذي تحمّله هذه الأداة متأخرًا.المصدر المضمَّن تحت exploit/ يحتفظ بترخيصه من المصدر الأعلى (Apache-2.0 للاستغلال المشتق من NebuSec). هذا المشروع محايد تجاه المدير: يحمّل متأخرًا أي نسخة KernelSU مثبَّت مديرها ولا يستهدف أو يضمّن أي فرع محدد.
ksudinit_module واكتشاف السائقapk_sign.rspipe_bufferashmem_miscs[0].fops بـ file_operations مزوَّر كل خانة فيه تشير إلى دالة نواة حقيقية متوافقة النموذج (configfs_bin_write_iter وconfigfs_read_iter وcopy_splice_read وashmem_ioctl وnoop_llseek، …)، بحيث يكون CFI للحافة الأمامية مستوفى بينما تعطي read/write/splice على واصف ashmem وصولًا مقيدًا للقراءة/الكتابة على النواة.pipe_buffer على صفحة slab المسرَّبة (page موجهة إلى أي هدف عبر تحويل vmemmap↔الخريطة المباشرة، وops = anon_pipe_buf_ops، وPIPE_BUF_FLAG_CAN_MERGE)، بحيث تنقل read()/write() العادية على الأنبوب بايتات من وإلى عناوين نواة عشوائية — وصول قراءة/كتابة مستقر وعشوائي على النواة./proc/sys/kernel/random/boot_id الحي مع الإقلاع المسجَّل وقت الالتقاط؛ أي تغيير يتجاهل القاعدة ويعود إلى المرحلة أ. حلقة خارجية تكرر اشتقاق→إعادة تشغيل عبر عمليات الإقلاع.umount| الحمولة | KMI | مبنية من | الأجهزة |
|---|
android14-6.1-a | android14-6.1 | bluejay-CP2A.260705.006 | oriole, raven, bluejay (CP2A), panther, cheetah, comet, shiba, husky, lynx, caiman |
android14-6.1-b | android14-6.1 | komodo-CP2A.260705.006 | komodo, tegu, tokay |
android14-6.1-akita | android14-6.1 | akita-CP2A.260805.005 | akita |
android14-6.1-cp1a | android14-6.1 | bluejay-CP1A.260405.005 | bluejay (CP1A) |
android15-6.6 | android15-6.6 | blazer-CP2A.260705.006 | frankel, blazer, mustang, rango |