
إعادة إنشاء استغلال لـ cve-2023-21768.
سبب: عند مقارنة AFD.sys في إصدارات 202209 و202307، في الدالة AfdNotifyRemoveIOCompletion، يستخدم كل من إصدار Windows 202209 و202307 دالة ProbeForWrite للتحقق من وجود منطقة ذاكرة في وضع المستخدم، ولكن عنوان المخزن المؤقت الذي يتم فحصه يختلف بمقدار 0x8 بايت. وقبل تصحيح الثغرة، لم يكن هذا الفحص موجودًا، لذا يمكن الافتراض أن عنوان الفحص في إصدار 202209 ربما كان غير صحيح وبالتالي غير فعال. هذا الفحص يرتبط بتعيين وسيط: **(_DWORD **)(a3 + 24) = v20; حيث من المفترض أن يكون المخزن المؤقت الذي يتم فحصه هو a3+24، وقيمة v20 مرتبطة بـ v8 = IoRemoveIoCompletion(v25, Pool2, v4, (unsigned int)v6, &v20, a1, v13, 0)، حيث يبدو أن Pool2 وv4 وv13 على الأقل يتم تحديدها بواسطة البنية غير المعروفة التي تمرر من وضع المستخدم. لذا يُفترض أن قيمة v20 مرتبطة أيضًا بتلك البنية التي تمرر من وضع المستخدم ~ (بعد الاطلاع على writeup، يبدو أنها القيمة المرجعة من KeRemoveQueueEx التي تستدعيها IoRemoveIoCompletion).
إذا كان a3+24 يخزن عنوانًا في وضع النواة، فقد يؤدي ذلك إلى إنشاء primitive لكتابة عشوائية في النواة (kernel arbitrary write)، ومن ثم يمكن استغلالها عبر IORING ~ (طريقة الاستغلال: https://windows-internals.com/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/)
بيئة إعادة الإنتاج: Visual Studio 2022 + Windows 11 202209 (يعمل على Hyper-V) مع خيار الترجمة x64 Release، وبسبب مشكلة vcruntime140.dll المفقودة في Hyper-V، تم استخدام الارتباط الثابت (static linking).
سلسلة الدوال داخل AFD.sys: AfdFastIOdeviceControl ← AfdNotifySock ← AfdNotifyRemoveIOCompletion، والتي تقوم بتعيين أحد حقول بنية غير معروفة إلى عنوان يحدده وضع المستخدم، مما يؤدي إلى إنشاء primitive لكتابة عشوائية في النواة، ثم يتم استغلالها بواسطة IORing.
تنفيذ الاستغلال (exploit): يتم تحقيق الكتابة العشوائية عبر دالة ArbitraryKernelWrite0x1، والتي يعتمد الجزء الرئيسي منها على إعادة استخدام أداة من x86matthew لتجاوز Winsock والتفاعل مباشرة مع AFD.sys (كانت الأداة في الأصل لإنشاء مقبس TCP مباشرة) (https://www.x86matthew.com/view_post?id=ntsockets).
البنية التي تتم الكتابة إليها عشوائيًا هي struct*AFD_NOTIFYSOCK_DATA* (أي البنية غير المعروفة سابقًا)، وقد تم تصميم مكوناتها المختلفة لتجاوز الفحوصات المختلفة في سلسلة الدوال.
المعامل الأول، وهو الـ handle، يتم إنشاؤه باستخدام الدالة غير الموثقة NT NtCreateIoCompletion (https://securityintelligence.com/x-force/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/).
تحديث حول تجربة التصحيح (debugging): من الملاحظ أن الشيفرات المتشابهة جدًا قد تتعطل في أماكن غريبة أثناء التصحيح.
على سبيل المثال، في البداية عند استدعاء _NtCreateFile كان المعامل الأول هو hSocket، ثم كانت __imp_ObReferenceObjectByHandle ترجع دائمًا قيمًا سالبة. بعد النظر، تم تعريف handle آخر لاستخدامه كمعامل لكل من _NtCreateFile و_NtDeviceIoControlFile (يبدو أن هاتين الدالتين تتفاعلان بشكل أساسي مع afd.sys، ويمكن الرجوع إلى مقالة x86matthew).
أيضًا، في البداية لم يتم استدعاء NtSetIOCompletion، مما تسبب في فشل فحص IORemoveIOCompletion. لذلك تم الرجوع إلى مقالة https://securityintelligence.com/x-force/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/.
ثم في مجموعة shadow، طلبت مساعدة بشأن عدم تحميل جداول الرموز (symbol tables)، واتضح أن السبب هو أن جهاز Windbg لم يكن متصلاً بالإنترنت عبر VPN، لذا لم يتمكن من الاتصال بجداول الرموز عبر الإنترنت.
أخيرًا، لاستخدام Windbg لتصحيح برنامج يعمل على Hyper-V، لم تكن العملية معقدة كما هو موصوف في Microsoft Learn؛ يكفي تشغيل bcdedit /debug on وbcdedit /dbgsettings net hostip:(عنوان IPv4 للمحول الافتراضي Ethernet على المضيف) port:50001 key:1.2.3.4 في موجه أوامر Hyper-V.
يحتوي الملف المضغوط (zip) على مشروع Visual Studio كامل لإعادة الإنتاج.
أخيرًا، شكر خاص للأخت Tingting وللزميل Mimi الذي ساعد في استكشاف أخطاء Windbg.