Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-64468 — إثبات مفهوم غير مميز ورفع صلاحيات محلي لمعمارية x86_64 لثغرة استخدام بعد التحرير (use-after-free) في نواة لينكس Binder (CVE-2026-64468)، مع مختبر KASAN وفرق تفاضلي بين النسخة الضعيفة والمصححة. | Kitploit
أدوات/GitHubGitHub/aramosf/cve-2026-64468
تصعيد الامتيازاتأطر الاستغلالتحليل الثغرات الأمنيةالاستغلالالتعلم والتعليماستغلال الملفات الثنائية
GitHubaramosf/cve-2026-64468

CVE-2026-64468

إثبات مفهوم غير مميز ورفع صلاحيات محلي لمعمارية x86_64 لثغرة استخدام بعد التحرير (use-after-free) في نواة لينكس Binder (CVE-2026-64468)، مع مختبر KASAN وفرق تفاضلي بين النسخة الضعيفة والمصححة.

عرض المستودع
29727منذ شهر واحدتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة

CVE-2026-64468 — استخدام بعد التحرير في دورة حياة العملية في binder_free_transaction() بنواة لينكس Binder

تشغيل مباشر على QEMU/KVM: النواة غير المُصححة المعرّضة للثغرة تُبلغ عن استخدام بعد التحرير، بينما النواة المُصححة لا تفعل

يحتوي هذا المستودع، لثغرة استخدام بعد التحرير في Binder بنواة لينكس التي تم إصلاحها بواسطة الالتزام العلوي f223d27a546c1e1f48d38fd67760e78f068fe8c4:

  • binder_chain_64468.c — إثبات مفهوم غير مميَّز يصل إلى الثغرة ويجعل النواة تُثبتها، مع مختبر KASAN و مقارنة تفاضلية بين النواة المعرّضة والمُصححة (lab/, run.sh, verify.sh).
  • exploit.c — تصعيد صلاحيات محلي مستقل لمعمارية x86_64. يُترجم باستخدام gcc -O2 -pthread -o exploit exploit.c، ويُشغَّل كمستخدم عادي، وينتهي بصدفة صلاحيات جذر.
  • demo/ — مختبر يُقلع ببيئة مستخدم Debian 13 حقيقية على نواة غير مُصححة، بحيث يمكن ترجمة الاستغلال بواسطة gcc الخاص بالهدف نفسه و تشغيله على الجهاز الذي يستولي عليه بعد ذلك.

يعمل كل شيء كمستخدم عادي (uid/gid 1000، بدون صلاحيات، بدون مساحات أسماء) ضد نواة علوية أصلية بدون أي تصحيحات من أي نوع.

تحذير

تتعمد هذه الشيفرة التنافس على أعمار كائنات النواة ثم تختطف تدفق التحكم في النواة. فقدان السباق يُفسد حالة كومة النواة ويمكن أن يُسبب تعليقًا أو انهيارًا للجهاز. شغّلها فقط في جهاز افتراضي معزول وقابل للتخلص تملكه. لا تشغّلها على مضيف.

الحالة والنطاق

الحالةالادعاء
مؤكَّدالثغرة حقيقية، ويمكن الوصول إليها من عملية غير مميَّزة، والإصلاح العلوي يزيلها.
مُثبَتإلغاء الإشارة المعرّض للثغرة إلى binder_proc المحتضر يُتحقق منه طبيعيًا وبشكل متكرر على النواة غير المُصححة، ولا يحدث أبدًا على النواة المُصححة.
مُثبَتاستخدام التحرير الكامل، كما أبلغ عنه KASAN، على النواة غير المُصححة.
مُثبَتاستعادة binder_proc المُحرَّر ببايتات يتحكم بها المهاجم، واختطاف تدفق التحكم في النواة، وتصعيد الصلاحيات إلى uid 0 من مستخدم غير مميَّز، على معمارية x86_64.
غير مُدَّعىأي نتيجة على جهاز بائع أو جهاز Android محدد. فقط النواة العلوية المذكورة أدناه تم اختبارها، على معمارية x86_64.
غير مُدَّعىأن الاستغلال المُرفق يعمل دون تعديل ضد نواة توزيعة. انظر أي الأنظمة المتأثرة: يتطلب إزاحات خاصة بكل نواة، وعلى كل توزيعة عامة تم مسحها، لا يمكن لمستخدم غير مميَّز الوصول إلى جهاز binder من الأساس.

الثغرة

يقرأ binder_free_transaction() العملية الهدف من المعاملة تحت t->lock، ثم يحرر هذا القفل، وبعد ذلك يكتسب القفل الداخلي للهدف:```c spin_lock(&t->lock); target_proc = t->to_proc; spin_unlock(&t->lock);

if (target_proc) {
	binder_inner_proc_lock(target_proc);   /* use after free */
لا شيء يُبقي `target_proc` حيّاً عبر تلك الفجوة. العملية التي يتم تفكيكها
بالتوازي يمكن أن تصل إلى `binder_proc_dec_tmpref() -> kfree()` في ما بين ذلك، لذا
يتم قفل الذاكرة المحرَّرة. الإصلاح في المنبع يثبّت `t->to_thread` بينما
`t->lock` ما زال محتفظاً به، مما يُبقي العملية المالكة حيّة حتى يتم استخدام
القفل الداخلي وتحريره.

تم الإبلاغ عن الثغرة بواسطة **Alice Ryhl** وتم إصلاحها بواسطة **Carlos
Llamas**، وكلاهما من Google. يحمل
[التقرير الأصلي](https://lore.kernel.org/all/[email protected]/)
أثر KASAN المرجعي.

### الوصول إلى المسار القابل للاستغلال

المستدعي الوحيد الذي يمكنه الوصول إلى `to_proc` *الأجنبي* هو
`binder_send_failed_reply()`، وهو لا ينتقل إلى `t->from_parent` إلا عندما يكون
`t->from` هو `NULL`:```c
	target_thread = binder_get_txn_from_and_acq_inner(t);
	if (target_thread) { ...; binder_free_transaction(t); return; }
	next = t->from_parent;
	binder_free_transaction(t);
	t = next;

from_parent يُعيَّن في مكان واحد بالضبط، ويكون هذا التعيين محميًا قبل بضعة أسطر بواسطة فحص مكدس المعاملات السيئ الخاص بـ binder: لا يُسمح للخيط بإرسال معاملة متزامنة إلا إذا كان أعلى مكدسه معاملةً يكون يستقبلها. لذلك، بالنسبة لكل حلقة في تلك السلسلة، يكون مُرسِل الطفل ومُستقبِل الوالد نفس الخيط.

يترتب على ذلك نتيجة حادة. binder_thread_release() يجتاز مكدس الخيط المُحتضَر مع الاحتفاظ بـ proc->inner_lock، ويكتب كلاً من``` iteration j : [holds child->lock ] child->from = NULL ; unlock child->lock spin_lock(parent->lock) iteration j+1 : [holds parent->lock] parent->to_proc = NULL

في **التكرارات المتجاورة لمسار واحد**، كل منها تحت
`t->lock` الخاص بها. لا يكتشف المُتجوّل أن `child->from == NULL` إلا بعد أن يحرّر المسار
قفل `child->lock`، ويحتاج إلى `parent->lock` للقطة الخاصة به. لذا فإن الفرصة
الكاملة هي الفجوة بين `spin_unlock(&child->lock)` لذلك المسار و
`spin_lock(&parent->lock)` الخاص به — بضع تعليمات. المسار المُحرِّر يحمل قفل دوران
ولا يمكن استباقه هناك؛ فقط المقاطعة يمكنها تأخيره.

لهذا السبب تكون السباق ضيقة ولماذا يكون كل من إثبات المفهوم
والاستغلال احتماليين.

### ما يبنيه إثبات المفهوم

`binder_chain_64468.c` يبني أقصر سلسلة تصل إلى
الوصول الضعيف، بحيث يكون عمل المُتجوّل داخل تلك الفجوة صغيرًا قدر ما يسمح به
binder — عمليتا اكتساب لـ `t->lock` و `kfree()` واحدة، دون أي
`inner_proc_lock` خارجي، ولا `wake_up` ولا تسليم رد:```
  B thread i   --e2 (sync, code 0x4442414b)-->  P thread Y_i
  P thread Y_i --e1 (sync, code 0x54414c4c)-->  B thread i   (nested target)

  B thread i   stack: [ e2 outgoing , e1 incoming (top) ]
  P thread Y_i stack: [ e2 incoming , e1 outgoing (top) ]

P ثم يُسقط واصف binder الخاص به، لذا يقوم binder_deferred_release() بتحرير Y_1..Y_K وأخيرًا يحرر binder_proc، بينما كل خيط B يصدر بشكل متزامن BINDER_THREAD_EXIT:``` binder_thread_release(B_i) nulls e1->to_proc (own proc) and e2->from binder_send_failed_reply(e1) e1->from == NULL once Y_i was released -> binder_free_transaction(e1) target_proc already NULL, kfree(e1) -> binder_free_transaction(e2) target_proc == P <-- vulnerable access

العملية الثالثة هي مدير سياق binder، وتُستخدم فقط لتوزيع
المقابض التي تحتاجها العمليتان الأخريان. `exploit.c` يعيد استخدام هذا البناء بالضبط.

### شرطان مستقلان

تقرير KASAN يتطلب كليهما:

* **الوصول الضعيف** — يجب أن يأخذ المتجول `parent->lock` داخل
  النافذة الضيقة أعلاه، بحيث يلتقط لقطة لـ `to_proc` الذي لا يزال حيًا؛ و
* **هبوط التحرير داخل النافذة** — يجب أن يفقد المتجول بعد ذلك وحدة المعالجة المركزية
  بين إسقاط `t->lock` وأخذ القفل الداخلي للضحية، ويبقى بعيدًا عنها
  حتى يكتمل التحرير المؤجل ويُحرَّر `binder_proc`.

الشرط الأول له مؤشر خاص به لا يحتاج إلى KASAN: binder يطبع```
binder: binder_free_proc: Unexpected outstanding_txns -1

عندما يحدث ذلك، لأن المتجول وbinder_thread_release() كلاهما يخفضان نفس العداد لمعاملة واحدة. لاحظ أن هذا ليس فرقًا قابلًا للاستغلال/الإصلاح بحد ذاته — الإصلاح يوقف التحرير، وليس الخفض الثاني — لذلك يظهر على كلا النواتين. يُستخدم هنا فقط لإظهار مسار الكود القابل للاستغلال وهو قيد التنفيذ.

من الاستخدام بعد التحرير إلى الجذر

يتوقف إثبات المفهوم عند خفض 4 بايت من الذاكرة المحررة. تحويل ذلك إلى uid 0 يتطلب أربعة أشياء، ولا يأتي أي منها من الثغرة نفسها: الثغرة لا تسرّب شيئًا.

1. ذاكرة تخزين مؤقت مشتركة

struct binder_proc يبلغ 648 بايت ويُخصص باستخدام GFP_KERNEL kzalloc عادي — وليس __GFP_ACCOUNT. لذلك يقع في kmalloc-1k، جنبًا إلى جنب مع كل تخصيص غير محسوب آخر بنفس الحجم، ولا يكون معزولًا خلف kmalloc-cg-*. هذه الحقيقة الواحدة هي ما يجعل الكائن قابلًا للاسترداد أصلًا.

2. مضخة استرداد تواكب السرعة

لحظة kfree() غير قابلة للملاحظة من مساحة المستخدم، وكذلك لحظة لمس المتجول للكائن مرة أخرى، لذلك لا يوجد شيء للتوقيت بناءً عليه. لذلك يعمل الرش كمضخة: يخصص ويحرر كائنات kmalloc-1k بشكل مستمر، من وحدة المعالجة المركزية التي نفّذت التحرير المؤجل، طالما أن المتجولين يعملون.

تُستخدم رسائل System V لهذا الغرض. alloc_msg() هو kmalloc غير محسوب عادي لرأس 48 بايت بالإضافة إلى الحمولة، لذا فإن رسالة بحجم 976 بايت هي تخصيص بحجم 1024 بايت؛ الحصة لكل قائمة انتظار وليست لكل uid؛ وmsgrcv() يحرر بشكل متزامن. الإنتاجية المُقاسة: ~198,000 تخصيصًا في الثانية، صفر فشل.

تنزيل الأداة