
ثغرتان في نواة النظام في Razer Lycosa.sys (CWE-125 كشف الذاكرة + CWE-121 تجاوز سعة المكدس) مرتبطتان لتصعيد الصلاحيات محليًا. مواد الإفصاح المنسّق، تم التحقق منها على Windows 11.
تم اكتشافهما عبر https://github.com/416rehman/DeepZero
المورّد: Razer Inc.
المكوّن: Lycosa.sys، برنامج تشغيل مرشّح لوحة مفاتيح Razer Lycosa، x64
SHA-256: a120a6184ab16864e8a5f1dfd0cd178fca541de463b5cef946e18c34b9b6f716
مرجع المُبلِّغ: a120a6184ab16864
الحالة: لم يُبلَّغ عنه للمورّد بعد.
يُبلِّغ هذا الدليل عن عيبين متميّزين في نفس الروتين من نفس برنامج التشغيل. لكلٍّ منهما سبب جذري منفصل وإصلاح منفصل، لذا لكلٍّ منهما مجلّده المستقل الخاص به ويمكن تتبّعه وإسناد معرّف خاص به:
| CVE | العيب | النوع | النتيجة |
|---|---|---|---|
| CVE-01 | لا يتم التحقق من طول المخرجات مقابل المخزن المؤقت، فيعيد برنامج التشغيل ذاكرة مكدّس النواة | CWE-125 قراءة خارج الحدود | كشف ذاكرة النواة، يُبطل عشوائية تخطيط فضاء العناوين |
| CVE-02 | لا يتم التحقق من طول المدخلات مقابل المخزن المؤقت، فيستبدل برنامج التشغيل عنوان العودة الخاص به | CWE-121 تجاوز سعة مخزن المكدّس | تنفيذ تعليمات برمجية عشوائية في النواة |
كلاهما يمكن الوصول إليه من أي حساب قادر على تسجيل الدخول وتشغيل برنامج. لا حقوق إدارية، ولا رفع صلاحيات، ولا امتياز خاص. تم تأكيد كليهما على Windows 11 25H2 (إصدار 26200.8875) مع تفعيل سلامة التعليمات البرمجية وإيقاف توقيع الاختبار.
يصف القسم 3 ما يعنيه الاثنان عند استخدامهما معًا، وهو السبب في الإبلاغ عنهما في الوقت نفسه وفي وجود إثبات المفهوم المتسلسل في هذا المجلد الجذري.
كلاهما يوجد في معالج IRP_MJ_DEVICE_CONTROL عند RVA 0x1270، وكلاهما يعمل على نفس المخزن المؤقت بحجم 0x400 بايت على مكدّس النواة. المقدّمة، المقروءة من الملف التنفيذي المُوزَّع، تحدّد الهندسة لكليهما:
Lycosa+0x1270 48 89 54 24 10 mov [rsp+10h], rdx ; Irp
Lycosa+0x1275 48 89 4c 24 08 mov [rsp+8], rcx ; DeviceObject
Lycosa+0x127a 48 81 ec 98 04 00 00 sub rsp, 498h ; the frame
Lycosa+0x1291 ba 00 04 00 00 mov edx, 400h ; the buffer size
Lycosa+0x1296 48 8d 8c 24 80 00 00 00 lea rcx, [rsp+80h] ; the buffer
مخزن مؤقت بحجم 0x400 بايت عند rsp+0x80، داخل إطار بحجم 0x498 بايت، دون حفظ أي سجلات غير متطايرة. بالعدّ من بداية المخزن المؤقت:
0x000 .. 0x3FF المخزن المؤقت، الذي يُفترض أن يبقى كلا العيبين داخله
0x418 عنوان العودة لروتين الإرسال
0x420 وسيط DeviceObject المحفوظ
0x428 وسيط Irp المحفوظ
0x418 هو 0x498 - 0x80. الكشف (CVE-01) يقرأ بعد 0x3FF ويعيد ما يجده؛ والتجاوز (CVE-02) يكتب بعد 0x3FF ويستبدله.
ينشئ DriverEntry الجهاز دون واصف أمان وينشر رابطًا رمزيًا له، لذا يمكن الوصول إليه عند \\.\Lycosa:
IoCreateDevice(param_1, 0x20, L"\\Device\\Lycosa", 0x22, 0, 0, &device);
IoCreateSymbolicLink(L"\\DosDevices\\Lycosa", L"\\Device\\Lycosa");
كل رمز تحكّم متأثّر يُفكّ ترميزه كـ FILE_DEVICE_UNKNOWN، METHOD_BUFFERED، FILE_ANY_ACCESS. تعني FILE_ANY_ACCESS أنه لا يجب امتلاك أي حق وصول معيّن على المقبض، لذا فإن واصف أمان كائن الجهاز هو البوابة الوحيدة، وهو يمنح الوصول للجميع.
جميع النتائج في هذه التقارير تم إنتاجها من حساب مستخدم قياسي عضويته الوحيدة في المجموعات هي مجموعة Users المدمجة. لم يكن للحساب أي حقوق إدارية، ولم يكن مرفوع الصلاحيات، ولم يحمل أي امتيازات تتجاوز الإعدادات الافتراضية.
كما يُحمَّل برنامج التشغيل على أجهزة لم تُوصَل بها أبدًا أجهزة Razer، لأن الحزمة موقّعة بشكل صحيح بكتالوج. هذا هو النمط المستخدم في هجمات إحضار برنامج تشغيل ضعيف خاص بك.
تم الإبلاغ عنهما بشكل منفصل لأنهما عيبان منفصلان، لكن على المورّد الذي يفرزهما أن يعلم أن كلًّا منهما يزيد الآخر سوءًا.
يُحمِّل Windows الحديث النواة على عنوان عشوائي. لا يزال على المهاجم القادر على استبدال عنوان العودة أن يعرف ما سيستبدله به، وهذه عادةً هي العقبة. يجيب برنامج التشغيل هذا على كلا السؤالين بنفسه:
CVE-01 يزيل العشوائية. يعيد الكشف عنوان العودة الخاص بروتين الإرسال، وهو عنوان تعليمات برمجية داخل ntoskrnl.exe. بطرح إزاحته المعروفة داخل الصورة نحصل على القاعدة التي تُحمَّل عندها النواة، ومن هناك يصبح كل عنوان داخل النواة معروفًا. هذا لا يكلّف شيئًا ولا يعكّر شيئًا.
CVE-01 يوفّر أيضًا القيمة التي يحتاجها CVE-02 لكي لا يحدث خطأ. كما هو موصوف في القسم 4.4 من CVE-02، يعيد برنامج التشغيل تحميل Irp من الإزاحة 0x428 أثناء خروجه ويكتب من خلاله. التجاوز الساذج الذي يصل إلى عنوان العودة يدمّر أيضًا ذلك المؤشر ويحدث خطأ قبل أن يعود الروتين. أما الاستغلال الموثوق فيوقف النسخ بالضبط عند 0x428، تاركًا Irp الحيّ للطلب الحالي في مكانه، فيكتمل برنامج التشغيل بشكل طبيعي.
ثم يعيد CVE-02 توجيه التنفيذ، مع كون قاعدة النواة معروفة بالفعل.
من حساب غير مميّز، يقرأ إثبات المفهوم المتسلسل الإطار، ويحسب قاعدة النواة وعنوان المخزن المؤقت نفسه في النواة، ويرسل سلسلة موجّهة نحو العودة:
step 1, read what is above the buffer on the kernel stack:
+0x418 return address 0xFFFFF807D565CABB
+0x498 frame pointer 0xFFFFFD042D313750 (read twice, must match)
step 2, turn those into the two addresses the payload needs:
kernel base = 0xFFFFF807D565CABB - 0x25CABB = 0xFFFFF807D5400000
buffer on stack = 0xFFFFFD042D313750 - 0x500 = 0xFFFFFD042D313250
step 4, overflow with a chain that:
pivots the stack onto the buffer, calls nt!ZwCreateFile, and
resumes nt!IopfCallDriver+0x5b
sending 0x428 bytes
call returned: accepted=true error=0
PROOF: C:\Windows\System32\dz_lycosa_kernel_exec.txt now exists.
هذه هي السلسلة الكاملة، تم التحقق منها من البداية إلى النهاية. أنشأ الحساب غير المميّز ملفًا تحت C:\Windows\System32، وهو مجلد يُرفض له الوصول للكتابة إليه في الأحوال العادية، عبر تنفيذ nt!ZwCreateFile في وضع النواة. تعني accepted=true أن استدعاء النظام عاد بشكل طبيعي: تستأنف السلسلة العنوان الدقيق الذي كان برنامج التشغيل سيعود إليه (nt!IopfCallDriver+0x5b، وهو add rsp,0x38 ; ret)، فينتهي الخيط ويستمر الجهاز في العمل. تم تأكيد الملف المُنشأ بشكل مستقل من صدفة مسؤول. النص الكامل موجود في logs/exec_create_file.log، والطريقة في METHODOLOGY.md.
القراءة العملية هي أن برنامج التشغيل هذا وحده يوفّر، لأي مستخدم للجهاز، كلا النصفين لما يُحتاج عادةً لتحويل عيب في سلامة الذاكرة إلى تنفيذ تعليمات برمجية في النواة: كشف العنوان الذي يزيل العشوائية، واختطاف تدفّق التحكّم الذي يستخدمه. معًا ثبت أنهما يُنتجان إجراءً مميّزًا ملموسًا مع بقاء الجهاز يعمل.
الإصلاحان مستقلان وكلاهما صغير، ومذكوران بالكامل في كل تقرير:
OutputBufferLength، وضبط IoStatus.Information على ما تم إنتاجه فعليًا.InputBufferLength.يوصي كلا التقريرين أيضًا بإنشاء جهاز التحكّم باستخدام IoCreateDeviceSecure وسلسلة SDDL تقصره على المسؤولين والنظام. هذا وحده لن يُصلح أيًّا من العيبين، لكنه سيزيل الوصول غير المميّز الذي يمنح كليهما خطورتهما.
تم التحقق قبل الكتابة، لأن التقرير المكرّر يهدر وقت المورّد:
https://aka.ms/VulnerableDriverBlockList والبحث عبر قواعد الحظر البالغ عددها 1,713. لا يظهر هذا الملف. برنامج تشغيل Razer الوحيد في تلك القائمة هو Rzpnk.sys، وهو مكوّن مختلف.نعتقد أن كلا العيبين غير مُبلَّغ عنهما سابقًا ونرحّب بأي تصحيح.
تشترك عدة برامج تشغيل أخرى مُوزَّعة في نفس مجلد الحزمة في الشكل العام لبرنامج التشغيل هذا وتُفحص بشكل منفصل. لا شيء هنا يُعدّ تصريحًا بشأنها.
pnputil /add-driver Flter2K.inf /install
sc create lycosa_test type= kernel binPath= C:\path\to\Lycosa.sys start= demand
sc start lycosa_test
لكل عيب إثبات مفهوم أحادي الغرض في مجلده، ويحتوي هذا الجذر على الإثبات المتسلسل الذي يجمعهما:
# CVE-01, reads only, safe to run anywhere, quickest confirmation of the report
rustc -O CVE-01-kernel-memory-disclosure/poc/lycosa_disclosure.rs -o disc.exe
disc.exe
# CVE-02, stops the machine by design
rustc -O CVE-02-kernel-stack-overflow/poc/lycosa_overflow.rs -o ovf.exe
ovf.exe --yes-crash-this-machine
# the chain: CVE-01 + CVE-02 into a file created in System32, machine left running
rustc -O poc/lycosa_chain.rs -o chain.exe
chain.exe --exec # default target under System32
chain.exe --exec C:\Users\Public\proof.txt # or any path you choose
شغّل كل شيء من حساب مستخدم قياسي. يذكر إثبات المفهوم المتسلسل ثابتي برنامج التشغيل اللذين يعتمد عليهما (FRAME وBUF_AT) في أعلى مصدره، لذا يمكن توجيهه إلى بناء مختلف لبرنامج التشغيل بتغيير هذين الرقمين. إزاحات النواة التي يستخدمها وضع --exec خاصة ببناء واحد من Windows؛ يتحقق البرنامج من قاعدة النواة المشتقّة في وقت التشغيل ويُبلِّغ وضعه --calibrate عن القيمة الوحيدة التي تتغيّر بين عمليات البناء.
README.md this overview and the chaining analysis
METHODOLOGY.md how both were found and confirmed, in order
poc/lycosa_chain.rs the CHAINED proof of concept (both defects)
evidence/ the binary, its package, decompiled sources, dumps
logs/exec_create_file.log transcript of the chained run in section 3
CVE-01-kernel-memory-disclosure/ standalone disclosure for the out-of-bounds read
README.md, poc/lycosa_disclosure.rs, evidence/, logs/
CVE-02-kernel-stack-overflow/ standalone disclosure for the stack overflow
README.md, poc/lycosa_overflow.rs, evidence/, logs/