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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
GhostLock-GOT-W29 — بحث حول CVE-2026-43499 (GhostLock) على HUAWEI MatePad Pro 11 GOT-W29 | Kitploit
أدوات/GitHubGitHub/zzzxxxxxxxxxx/ghostlock-got-w29
تصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالالهندسة العكسيةأمن الجوالاستغلال الملفات الثنائية
GitHubzzzxxxxxxxxxx/ghostlock-got-w29

GhostLock-GOT-W29

بحث حول CVE-2026-43499 (GhostLock) على HUAWEI MatePad Pro 11 GOT-W29

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

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-43499 (GhostLock) — HUAWEI MatePad Pro 11 GOT-W29

بحث استغلال صلاحيات (privilege escalation) على GOT-W29 (HarmonyOS 4.0، kernel 4.19.157-perf+) بخصوص CVE-2026-43499 (rtmutex/futex-PI stack UAF، "GhostLock").

النتيجة النهائية

  1. الثغرة حقيقية وقابلة للاستغلال: حلقة PI التي تحمل القيمة تجعل FUTEX_CMP_REQUEUE_PI يُرجع -EDEADLK، ومسار التراجع يُفعّل خطأ التنظيف current != waiter->task في remove_waiter() (في هذا النواة kernel/locking/rtmutex.c:1110-1112، الإصلاح upstream 3bfdc63936dd)، فيصبح pi_blocked_on الخاص بالـ waiter معلّقًا (يشير إلى rt_waiter عند E-0x1b0 في kernel stack الخاص به).
  2. البدائية الكتابية (write primitive) تم التحقق منها من الطرف إلى الطرف بمساحة مستخدم خالصة (QEMU kernel.patched، بدون حقن GDB/KPM): تعليق EDEADLK → setsockopt(SOL_IP, MCAST_BLOCK_SOURCE, group_source_req 0x108) يسلّم fake waiter (نقطة هبوط copy عند E-0x210، والـ waiter موضوع عند buf+0x60 ليغطي E-0x1b0 بالضبط) → sched_setattr يُفعّل walk → rb_erase يكتب sysctl_bootid، والأداة تتحقق ذاتيًا write_ok=1 (أعلى 8 بايت من boot_id = 0xffffff800b412320).
  3. استنتاج "عقدة التسليم" المبكر تم سحبه: المسح القديم حسب إطار 0x80 الخاص بـ sock_setsockopt ضمن سلسلة setsockopt. التفكيك + اختبار QEMU الفعلي يؤكدان أن __arm64_sys_setsockopt لـ level != SOL_SOCKET يستدعي blr ops->setsockopt مباشرة، دون المرور بـ sock_setsockopt؛ بعد التصحيح عمق نسخ do_ip_setsockopt = 0x210 (كان يُقدّر 0x290)، والهندسة مناسبة. الآليات المستبعدة: pselect/select، ptrace، import_iovec، ppoll، SCTP (قياس فعلي 0x158).
  4. العمل المتبقي على الجهاز: التحقق من سماح SELinux لـ MCAST setsockopt (نجح mrx تحت EMUI بهوية shell باستخدام نفس الناقل، ومن المتوقع أن يكون ممكنًا)، ومراجعة مسار الإرجاع/park على الجهاز الحقيقي (يمكن استخدام KPM لمراقبة W مباشرة)، وتكييف سلسلة ما بعد الاستغلال مع SELinux (الآلية مُنفّذة، انظر --root). فرق HKIP: جدول رموز نواة GOT-W29 والصورة لا يحتويان على hkip_*/ خطافات hypervisor، كما أن 97 تعليمة hvc في الصورة كاملة ليست على مسار cred/cap/SELinux (فقط KVM/SMCCC/برامج نقل التصحيح)، أي أن حماية hypervisor xid الخاصة بـ mrx على الأرجح غير موجودة على هذا الجهاز — يمكن على الجهاز الحقيقي اتباع مسار root العادي مباشرة.

الجهاز

البندالقيمة
الطرازHUAWEI MatePad Pro 11 GOT-W29
SoCQualcomm kona (SM8250, Snapdragon 870)
النظامHarmonyOS 4.0 (104.0.0.136)
النواة4.19.157-perf+ (تفكيك boot.elf + firmware/symtab.txt)
VA39-bit, 4K pages, KASLR on

الثغرة والتفعيل (النسخة النهائية)

شروط التفعيل

  • صلاحيات shell: adb shell أو Shizuku كلاهما يعمل.
  • تعطيل خدمتي التحكم الخلفي لدى هواوي، ليحصل عملية shell على cpuset الجذر (وإلا لن تدخل سلسلة التفعيل المسار الهدف):
pm disable-user com.huawei.powergenie
pm disable-user com.huawei.iaware

الآلية: إنشاء حلقة PI (waiter→target→owner→chain→waiter) لجعل FUTEX_CMP_REQUEUE_PI يسلك تراجع EDEADLK، وفي التراجع يستخدم remove_waiter(lock, waiter) current (خيط requeue) بدلًا من waiter->task للتنظيف: rt_mutex_dequeue يزيل عقدة الـ waiter الحقيقية، لكن pi_blocked_on الخاص بالـ waiter لا يُمسح (current->pi_blocked_on = NULL)، فيصبح مؤشرًا معلّقًا يشير إلى rt_waiter في kernel stack.

حلقة حمل القيمة (حلقة probe، مستقرة عمليًا عند -EDEADLK):

  • waiter: FUTEX_LOCK_PI(chain) يحمل chain؛ FUTEX_WAIT_REQUEUE_PI(wait, 0, target)
  • owner: FUTEX_LOCK_PI(target) يحمل target؛ FUTEX_LOCK_PI(chain) يحجب
  • main: FUTEX_CMP_REQUEUE_PI(wait, 1, target) → -EDEADLK
  • بعد انتهاء مهلة الـ waiter (WAIT_REQUEUE_PI 2s) يبقى pi_blocked_on المعلّق على الـ stack

ملاحظة: تفعيل "self-own" القديم، و-EDEADLK في edeadlk_probe variant 11، كلاهما خروج مبكر لـ owner==task (rtmutex.c:1035)، ولا ينتج مؤشرًا معلّقًا، فهو غير صالح.

النتائج

تسريب KASLR (perf_event_open، ممكن بهوية shell)

مع perf_event_paranoid=-1، يقوم perf_event_open(PERF_SAMPLE_IP, exclude_user=1) بأخذ عينات من عنقود نص النواة، وبمحاذاة إزاحات الرموز المعروفة نحصل على slide:

samples=27651 kernel_ips=1685 lo=0xffffff948728176c hi=0xffffff9488ebfc7c
KASLR slide=0x147f200000    runtime _stext=0xffffff9487280800

الأداة: tools/perf_kaslr.c.

تفعيل EDEADLK (إنشاء المؤشر المعلّق)

[M] CMP_REQUEUE_PI ret=-1 errno=35 (EDEADLK!)
[W] WAIT_REQUEUE_PI ret=-1 errno=110 (ETIMEDOUT)  ← waiter 返回، pi_blocked_on 悬空

الأداة: tools/edeadlk_probe.c.

البدائية الكتابية وسلسلة التسليم (تحقق QEMU من الطرف إلى الطرف، بدون حقن)

walk الخاص بـ rt_mutex_adjust_prio_chain يقرأ fake rt_waiter عند pi_blocked_on المعلّق:

  • [3] next_lock == waiter->lock (lock = خانة مستقلة في empty_zero_page، انظر أدناه)
  • [5] raw_spin_trylock(&lock->wait_lock) ينجح على قفل صفري
  • [7] rt_mutex_dequeue → مسار rb_erase ذو الابن الأيسر الوحيد: *(rb_left) = rb_parent_color → القيمة المكتوبة 0xffffff800b412320 (&loggers[0][1]) تُكتب في sysctl_bootid + 8
  • [9] عودة نظيفة بدون owner

لا حاجة لصفحة owner-ful / prepare_skb_payload / kernelsnitch. الـ rt_mutex المزيف لا يمكن إعادة استخدام نفس الخانة عبر walk: نهاية walk تترك waiters.root/leftmost في القفل مشيرًا إلى waiter هذه الجولة، وعند walk ثانٍ تُقرأ العقدة القديمة فيتم إلغاء الإشارة إلى kernel stack محرَّر من الجولة السابقة، مما يُفعّل BUG_ON(w->lock != lock) في rt_mutex_top_waiter() (قياس QEMU: الاختبار الثاني في --verify-all يُصاب بـ BUG مباشرة). في التنفيذ تُؤخذ لكل attempt خانة empty_zero_page + n*0x20 (إجمالًا 128 خانة، SLIDE_LOCK_STRIDE/SLOTS)، وهي صفرية بطبيعتها ولا تتلوث ببعضها.

مخرجات التحقق الذاتي للأداة في QEMU (kernel.patched، nokaslr، --probe-cycle --verify-all):

4.483 237 [+] slide write boot_id raw=00000000000000002023410b80ffffff lo=0 hi=ffffff800b412320 exp_lo=0 exp_hi=ffffff800b412320 ok=1
4.547 1   [+] slide write test PASSED
6.583 240 [+] slide leaf boot_id raw=00000000000000002023410b80ffffff lo=0 hi=ffffff800b412320 exp_lo=0 exp_hi=0 ok=1
6.636 1   [+] slide leaf test PASSED
8.671 243 [+] slide read boot_id raw=100000002401000030d74c0b80ffffff lo=0000012400000010 hi=ffffff800b4cd730 exp_lo=0000012400000010 exp_hi=ffffff800b4cd730 ok=1
8.724 1   [+] slide read test PASSED
10.811 1  [+] slide restore test PASSED
10.811 1  [+] slide verify all PASSED

(requeue=-1/35 trigger=0/0 wait=-1/110 carrier=-1/22 متسقة في كل attempt: EDEADLK، نجاح walk، انتهاء مهلة hrtimer، ونجاح نسخ الناقل قبل أن يُرجع EINVAL بسبب مجموعة العنوان المزيف.)

ملاحظة: هدف التحقق يكتب boot_id + 8: proc_do_uuid() يعيد توليد UUID كامل عندما يكون bootid[8] == 0، وكتابة أقل 8 بايت ستُغطى بقراءة التحقق نفسها (مؤكد بقياس QEMU).

أشكال البدائية الكتابية (فحص ذاتي شامل بـ --verify-all)

الشكلكلمات fake waiter tree الثلاثالتأثير
pointer (rb_erase Case 2: ابن أيسر وحيد)pc=value, right=0, left=target*(target) = value (64 بت كاملة، مع الحفاظ على بتات اللون)؛ أثر جانبي *(value+8) = target، لذا يجب أن يكون value قابلًا للقراءة وأن يكون +8 الخاص به قابلًا للتضحية
leaf (Case 1: بلا أبناء)pc=target-8, right=0, left=0*(target) = 0؛ كتابة نظيفة واحدة فقط (بلا أثر جانبي)، pc ببتات منخفضة=0 → RED → لا يُفعّل rebalance، لكن __rb_change_child سيقرأ *(target-8) مرة واحدة

البدائية القرائية (منقولة من قناة boot_id في mrx-w09)

بعد أن تُغيّر البدائية الكتابية random_table[4].data (= &sysctl_bootid، link 0xffffff800b4cd730؛ مؤكد من إدخال R_AARCH64_RELATIVE الوحيد في .rela.dyn بقيمة addend=0xffffff800b7f8b64) إلى العنوان الهدف A، فإن قراءة /proc/sys/kernel/random/boot_id تُرجع [A, A+16). ملاحظات:

  • proc_do_uuid() يعيد توليد UUID من 16 بايت عندما يكون ((u8 *)A)[8] == 0 (ويكتب فوق A)، لذا يجب أن تكون البايت 8 في نافذة القراءة غير صفرية؛
  • الأثر الجانبي للكتابة بالمؤشر يكتب A+8 = عنوان خانة .data، لذا يكون النصف الأعلى المقروء دائمًا عنوان تلك الخانة؛ عند الحاجة لقراءة 16 بايت بدقة يجب تجنب هذا الموضع.
تنزيل الأداة