تحت القصاصة هي ترجمة للعرض التقديمي "مرفق إعلام Windows: سطح هجوم النواة غير الموثق" المقدم من Alex Ionescu و Gabrielle Viala في مؤتمر BlackHat 2018 .


ما سيتم مناقشته في المنشور ما هو Windows Notification Facility (WNF)
Windows Notification Facility هي آلية إعلام (متوفرة في وضع kernel وفي وضع المستخدم) ، وهي تستند إلى نموذج الناشر-المشترك ( pubsub ، Publisher / المشترك). تمت إضافة الآلية في نظام التشغيل Windows 8: جزئيًا من أجل حل بعض قيود التصميم القديمة في نظام التشغيل ، ولكن أيضًا يجب أن تكون بمثابة أساس لتطبيق إعلامات الدفع المشابهة لنظام التشغيل iOS / Android.
الميزة الرئيسية هي أنه نموذج أعمى (معظمه بدون تسجيل) يسمح بالاشتراك والنشر غير المرتب. هذا يعني أنه يمكن للمستهلك الاشتراك في إشعار حتى قبل نشر الإشعار بواسطة مصدره. وأن الشخص الذي يولد الأحداث ليس مطلوبًا من "تسجيل" الإشعار مقدمًا.
بالإضافة إلى ذلك ، تدعم الآلية:
- إخطارات دائمة ومؤقتة
- زيادة رتابة معرفات فريدة من نوعها
- المخزن المؤقت الحمولة (يصل إلى 4 كيلو بايت) لكل حدث
- نموذج إعلام مؤشر ترابط - مجموعة مع التسلسل المستندة إلى المجموعة
- نموذج أمان يستند إلى نطاق يقوم بتطبيق واصفات الأمان من خلال آلية DACL / SACL القياسية
لماذا ظهرت WNF
فكر في مثال قانوني: يوجد برنامج تشغيل يريد أن يعرف أنه قد تم توصيل وحدة تخزين مع وصول للقراءة والكتابة. لإعلامك بهذا ، يبلغ Autochk (تناظرية fsck على Windows) عن حدث يسمى VolumesSafeForWriteAccess. ولكن من أجل الإبلاغ عن حدث ، يجب عليك أولاً إنشاء كائن الحدث نفسه.
نحتاج أيضًا إلى معرفة أن Autochk يعمل بالفعل على وحدة التخزين ، ولكن لم يشر بعد إلى الحدث الذي ننتظره. حل غير صحيح: الجلوس في حلقة مع وضع السكون () ، والتحقق من وجود حدث ، وعندما يتم إنشاء الحدث - انتظره.
ولكن بعد الخروج من تطبيق Windows ، يتم إغلاق جميع الواصفات الخاصة به. وعندما لا يحتوي الكائن على واصفات ، يتم تدميره. فمن الذي سيعقد هذا الحدث؟
بدون WNF ، يكمن الحل في قيام kernel OS بإنشاء حدث قبل تحميل أي من برامج التشغيل ، ولكي يقوم Autochk بفتحه كما يفعل المستهلك ، ولكن بدلاً من الانتظار ، يجب أن يشير إلى هذا الحدث.
أسماء الدول WNF
في عالم WNF ، اسم الولاية هو رقم 64 بت. ولكن هناك خدعة - في الواقع هو بنية مشفرة. يحتوي اسم الحالة على إصدار وعمر ونطاق وعلامة ثبات البيانات ورقم تسلسلي فريد .
typedef struct _WNF_STATE_NAME_INTERNAL { ULONG64 Version:4; ULONG64 NameLifetime:2; ULONG64 DataScope:4; ULONG64 PermanentData:1; ULONG64 Unique:53; } WNF_STATE_NAME_INTERNAL, *PWNF_STATE_NAME_INTERNAL;
لكن هذه البيانات لن تكون متاحة إلا إذا كنا نؤيد XOR رقم 64 بت مع ثابت ثابت:
#define WNF_STATE_KEY 0x41C64E6DA3BC0074
عمر اسم الولاية
يمكن أن يكون اسم حالة WNF (WNF_STATE_NAME_LIFETIME):
- معروف (معروفة)
- العادية (دائمة)
- مستقرة (مستمر)
- مؤقتة (مؤقت)
ترتبط الثلاثة الأولى بالمفاتيح المقابلة في السجل ، حيث سيتم تخزين معلومات الحالة:
- أسماء معروفة تعيش في HKLM \ SYSTEM \ CurrentControlSet \ Control \ الإخطارات
- الأسماء المستمرة تعيش في HKLM \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Notifications
- الأسماء المستمرة تعيش في HKLM \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ VolatileNotifications
الأسماء المعروفة لها خصوصية خاصة بها: لا يمكن تسجيلها. يجب تقديم هذا الاسم بالفعل في السجل وقت بدء تشغيل النظام. تتطلب الأسماء المستمرة والثابتة امتياز SeCreatePermanentPrivilege المضمّن (مثل الكائنات العامة الأخرى) لإنشائها. الأسماء الدائمة تعيش خارج عملية المسجل ، بينما تظل الأسماء الدائمة عملية إعادة تمهيد للنظام.
نطاق البيانات
يعرّف نطاق البيانات حدود الأمان الأولى حول اسم حالة WNF ؛ فهو يحدد من يراه ومن لديه حق الوصول إليه. يمكن أن يكون نطاق اسم الولاية:
- النظام
- السيارة
- جلسة المستخدم
- المستخدم
- هذه العملية
بالإضافة إلى توفير حدود الأمان ، يمكن استخدام نطاقات WNF لتوفير مثيلات مختلفة من البيانات بنفس الاسم. يتجاوز kernel (كما هو الحال مع آليات الأمان الأخرى) اختبارات الوصول إلى الحالة. يسمح امتياز TCB بالوصول عبر النطاق إلى أسماء حالة WNF.
نطاق "النظام" ونطاق "الآلة" نطاقان عالميان. ليس لديهم معرفات خاصة بهم (يستخدمون حاويات عالمية مختلفة). يستخدم نطاق جلسة المستخدم معرف الجلسة (معرف الجلسة) كمعرّف. يستخدم نطاق مستخدم معين معرف الأمان هذا المستخدم كمعرف. عنوان كائن EPROCESS هو معرف نطاق العملية.
أرقام التسلسل
لضمان التفرد ، يحتوي كل اسم ولاية على رقم تسلسلي فريد من 51 بت. تتضمن الأسماء المعروفة علامة عائلة مكونة من 4 أحرف في رقمها التسلسلي ، ويتم استخدام البتات الـ 21 المتبقية كمعرّف فريد. أسماء دائمة بتخزين عدد متزايد مع قيمة التسجيل "SequenceNumber". تستخدم الأسماء الثابتة والمؤقتة عداد زيادة شائع ، والذي يقع في متغير عمومي. يتم تخزين هذه البيانات ومعالجتها بشكل منفصل لكل حاوية (لكل صومعة) ، وتتوفر في PspHostSiloGlobals-> WnfSiloState.
داخل Microsoft ، يحتوي كل اسم WNF على معرف "مألوف" يُستخدم في التعليمات البرمجية ، وأحيانًا يتم تخزينه في مساحة الاسم العالمية بنفس الاسم. على سبيل المثال ، الرمز nt! WNF_BOOT_DIRTY_SHUTDOWN ، والذي له القيمة 0x1589012fa3bc0875. بعد XOR مع الثابت السحري WNF_STATE_KEY نحصل على القيمة 0x544f4f4200000801 ، والتي يمكن تفسيرها في اتجاه bitwise على أنها:
BOOT1, Well-Known Lifetime, System Scope, Version 1
نظام يدعو للعمل مع WNF
تتيح لك مكالمات نظام Kernel تسجيل وحذف أسماء حالات WNF ، ونشر واستقبال بيانات اسم حالة WNF ، وكذلك تلقي إشعارات متنوعة من WNF.
تسجيل اسم حالة WNF
باستثناء الأسماء المعروفة (كما ذكر سابقًا) ، يمكن تسجيل اسم حالة WNF أثناء تشغيل نظام التشغيل:
NTSTATUS ZwCreateWnfStateName ( _Out_ PWNF_STATE_NAME StateName, _In_ WNF_STATE_NAME_LIFETIME NameLifetime, _In_ WNF_DATA_SCOPE DataScope, _In_ BOOLEAN PersistData, _In_opt_ PCWNF_TYPE_ID TypeId,
يوجد نظام متماثل يسمى ZwDeleteWnfStateName والذي يمكنك من خلاله حذف اسم الحالة المسجل (مرة أخرى ، باستثناء الأسماء المعروفة).
نشر بيانات حالة WNF
لتعيين أو تغيير بيانات اسم حالة WNF ، يمكنك استخدام استدعاء نظام ZwUpdateWnfStateData:
NTSTATUS ZwUpdateWnfStateData ( _In_ PCWNF_STATE_NAME StateName, _In_reads_bytes_opt_(Length) const VOID* Buffer, _In_opt_ ULONG Length,
هناك نظام متماثل استدعاء ZwDeleteWnfStateData لحذف (تنظيف) بيانات اسم حالة WNF.
الحصول على بيانات حالة WNF
لطلب بيانات اسم حالة WNF ، يمكن استخدام استدعاء النظام التالي (تشبه معظم المعلمات وظيفة التحديث):
NTSTATUS ZwQueryWnfStateData ( _In_ PCWNF_STATE_NAME StateName, _In_opt_ PCWNF_TYPE_ID TypeId, _In_opt_ const VOID* ExplicitScope, _Out_ PWNF_CHANGE_STAMP ChangeStamp, _Out_writes_bytes_to_opt_(*BufferSize, *BufferSize) PVOID Buffer, _Inout_ PULONG BufferSize
تكمن القوة الحقيقية في حقيقة أن وظيفتي Update و Query API لا تتطلبان في الواقع اسم حالة WNF مسجل . وإذا لم يكن الاسم مؤقتًا (وكان لرمز الاتصال امتيازات كافية) ، فيمكن تسجيل مثيل الاسم في الوقت الفعلي!
إخطارات WNF
حتى الآن ، افترضنا أن المستهلك يعرف متى يتم استدعاء وظيفة الحصول على البيانات. ولكن هناك أيضًا حظر للقراءة ، والذي يعمل باستخدام نظام إعلام (وهو أقرب إلى نموذج الناشر والمشترك الحقيقي).
أولاً ، يجب أن تسجل العملية الحدث عن طريق استدعاء دالة ZwSetWnfProcessNotificationEvent. ثم تحتاج إلى استدعاء وظيفة ZwSubscribeWnfStateChange ، مع تحديد قناع حدث للحصول على معرف الاشتراك في الإخراج. يمكن أن تكون الأحداث من نوعين:
- إشعارات البيانات:
- 0x01 - ظهور البيانات
- 0x10 - تدمير الاسم
- ميتا Metanotifications
- 0x02 - ظهور مشترك يتلقى إشعارات البيانات (مشترك البيانات)
- 0x04 - ظهور مشترك يستقبل إشعارات التعريف (مشترك التعريف)
- 0x08 - ظهور مشترك يستقبل إشعارات البيانات والإشعارات الفوقية (مشترك عام)
ثم تحتاج إلى الانتظار لهذا الحدث الذي تم تسجيله. وفي كل مرة يصبح الحدث إشارة ، تحتاج إلى استدعاء وظيفة ZwGetCompleteWnfStateSubscription ، والتي تُرجع WNF_DELIVERY_DESCRIPTOR.
لكن وظائف API منخفضة المستوى هذه تواجه مشكلة (بفضل Gabi للتحقيق فيها): يمكن أن تحتوي كل عملية على حدث مسجل واحد فقط.
واجهة برمجة تطبيقات وضع المستخدم عالي المستوى (ntdll)
عندما يتعلق الأمر بالإشعارات ، تصبح الأمور معقدة ، بحيث توفر طبقة rtl من ntdll.dll واجهة أكثر بساطة:
NTSTATUS RtlSubscribeWnfStateChangeNotification ( _Outptr_ PWNF_USER_SUBSCRIPTION* Subscription, _In_ WNF_STATE_NAME StateName, _In_ WNF_CHANGE_STAMP ChangeStamp, _In_ PWNF_USER_CALLBACK Callback, _In_opt_ PVOID CallbackContext, _In_opt_ PCWNF_TYPE_ID TypeId, _In_opt_ ULONG SerializationGroup, _In_opt_ ULONG Unknown );
في الواقع ، ليست هناك حاجة للاتصال مباشرة بخدمات النظام: ما عليك سوى استخدام قائمة انتظار حدث واحدة تستند إلى ntdll.dll.
خلف الكواليس ، يتم تحويل محتويات WNF_DELIVERY_DESCRIPTOR إلى معلمات رد الاتصال:
typedef NTSTATUS (*PWNF_USER_CALLBACK) ( _In_ WNF_STATE_NAME StateName, _In_ WNF_CHANGE_STAMP ChangeStamp, _In_opt_ PWNF_TYPE_ID TypeId, _In_opt_ PVOID CallbackContext, _In_ PVOID Buffer, _In_ ULONG BufferSize);
لكل اشتراك جديد ، يتم إدخال إدخال ، يتم وضعه في القائمة التي يشير إليها المتغير العمومي RtlpWnfProcessSubscriptions. تم بناء القائمة على أحد الحقول WNF_NAME_SUBSCRIPTION ، وهو من النوع LIST_ENTRY. يحتوي كل من WNF_NAME_SUBSCRIPTION ، بدوره ، على LIST_ENTRY حقل آخر لتنظيم قائمة WNF_USER_SUBSCRIPTION مع رد اتصال وسياق.
واجهة برمجة تطبيقات المستوى العالي للنواة (سابقًا)
يوفر WNF أيضًا وظائف متطابقة تقريبًا لرمز وضع kernel (والذي يمكن استخدامه من برنامج التشغيل): سواء من خلال مكالمات النظام التي تم تصديرها أو من خلال وظائف API عالية المستوى في وقت التشغيل (طبقة Ex).
تقبل الدالة ExSubscribeWnfStateChange اسم الولاية ، اكتب الأقنعة وعنوان سياق وظيفة رد الاتصال + كمدخل ، وتقوم بإرجاع واصف اشتراك. تتلقى وظائف رد الاتصال اسم الهدف وقناع الحدث وتغيير التسمية ، ولكن ليس المخزن المؤقت أو حجمه.
تقوم الدالة ExQueryWnfStateData ، بناءً على واصف الاشتراك الذي تم تمريره ، بقراءة بيانات الحالة الحالية. في الواقع ، ينتهي كل رد اتصال باستدعاء وظيفة ExQueryWnfStateData للحصول على البيانات المرتبطة بالإعلام.
لكل من اشتراكات وضع kernel والاشتراكات في وضع المستخدم ، تنشئ WNF (لتتبع الاشتراكات) مثيلًا لبنية WNF_SUBSCRIPTION. ولكن بالنسبة لوضع المستخدم ، لن يتم ملء بعض الحقول ، على سبيل المثال رد الاتصال والسياق ، لأنه بالنسبة لوضع المستخدم ، يتم تخزين عناوين المعالجات ومعالجتها بواسطة ntdll.dll.
هياكل بيانات WNF

من المترجم : انظر القسم التالي.
المرافق تحليل WNF
من أحد المترجمين : تجدر الإشارة هنا مرة أخرى إلى أن العرض التقديمي لم يتم إجراؤه من قِبل أليكس فقط ، ولكن أيضًا بواسطة غابرييل فيالا . على وجه الخصوص ، ينتمي المؤلف الخاص به إلى وحدة WnfCom الموضحة أدناه. بالإضافة إلى ذلك ، وصف غابرييل الهياكل الداخلية لـ WNF بتفاصيل كافية (انظر الرسم التوضيحي في القسم السابق). معظم الشرائح الخاصة به ، للأسف ، غائبة في pdf للعرض التقديمي (يشار إليه على أنه الأصلي) أو يشار إليه حصريًا بالعناوين. ولكن:
ومن المترجم : إذا أراد شخص ما أن يكمل الترجمة الحالية بمحتويات Gabrielle الشرائح أو توسيع ترجمة الاختزال من أي جزء من فيديو الخطاب - مرحبًا بك. لتوفير الراحة لإضافة / تغيير مجموعات كبيرة ، يمكنني نشر مصدر الترجمة على جيثب (أو خادم آخر للتحكم في الإصدار).
WnfCom
WnfCom هي وحدة بيثون ( كود مصدر github ) تُظهر إمكانية التشغيل المتداخل من خلال WNF. الميزات الرئيسية:
- يسمح لك بقراءة / كتابة البيانات من مثيلات موجودة
- يسمح لك بإنشاء أسماء حالة مؤقتة ( كخادم )
- يتيح لك الحصول على مثيل لكائن العميل الذي سيقوم بمعالجة الإعلامات حول تغيير مثيل معين من الاسم
مثال للاستخدام:
>>> from wnfcomimport Wnfcom >>> wnfserver = Wnfcom() >>> wnfserver.CreateServer() [SERVER] StateNamecreated: 41c64e6da5559945 >>> wnfserver.Write(b"potatosoup") Encoded Name: 41c64e6da5559945, Clear Name: 6e99931 Version: 1, Permanent: No, Scope: Machine, Lifetime: Temporary, Unique: 56627 State update: 11 bytes written
>>> from wnfcomimport Wnfcom >>> wnfclient = Wnfcom() >>> wnfclient.SetStateName("41c64e6da5559945") >>> wnfclient.Listen() [CLIENT] Event registered: 440 [CLIENT] Timestamp: 0x1 Size: 0xb Data:00000000: 70 6F 74 61 74 6F 20 73 6F 75 70 potato soup
WnfDump
WnfDump هي أداة مساعدة لسطر الأوامر مكتوبة باللغة C. يمكن العثور على الملف القابل للتنفيذ على https://github.com/ionescu007/wnfun عن طريق تحديد الدليل الفرعي لعمق البت المطلوب. يمكن استخدام الأداة المساعدة للبحث عن معلومات حول أسماء حالات WNF:
- -d ( D ump) تفريغ كافة أسماء حالة WNF باستخدام تعداد يستند إلى التسجيل. يمكن استكماله بخيارات:
- -v ( V erbose) إخراج مطوّل يتضمن تفريغ سداسي عشري لبيانات حالة WNF ؛
- -s ( S ecurity) واصفات الأمان - سلاسل SDDL من أذونات لاسم حالة WNF.
- -b ( B rute-force) التعداد المباشر لأسماء حالة WNF المؤقتة (المزيد حول هذا أدناه)
- -i ( I nformation) عرض معلومات حول اسم حالة WNF واحد محدد
- -r ( R ead) قراءة البيانات من اسم حالة WNF المحدد
- -w ( W rite) اكتب البيانات إلى اسم حالة WNF المحدد
- -n ( N otification) تسجيل مشترك في الإشعارات لاسم حالة WNF المحدد (فيما يلي سيكون حالة استخدام أكثر تحديدًا مع Edge)
WNF سطح الهجوم
سيناقش هذا القسم (بتعبير أدق ، أقسامه الفرعية) الهجمات المحتملة وبيانات WNF الحساسة المثيرة للاهتمام.
الكشف عن البيانات المميزة
عند قراءة الآلاف من أسماء حالات WNF الموجودة في النظام ، يمكن الإشارة إلى العديد منها ، والتي تبدو بياناتها مثيرة جدًا للاهتمام. من بينها بعض البيانات التي تشبه بشكل مثير للريبة المؤشرات أو غيرها من البيانات المميزة.
بعد اللعب على العديد من الأجهزة ، في بعض الحالات ، كان من الممكن العثور على مجموعة بيانات ومجموعات معلومات مميزة أخرى تم الكشف عنها عبر حدود الامتياز. تم إرسال تقارير الأخطاء / الضعف إلى MSRC في يوليو ، ولكن تم تصحيحها في نوفمبر (بعد العرض التقديمي). على سبيل المثال: 4 كيلو بايت من المكدس تسربت خلال الحدث WNF_AUDC *!
المشاكل الرئيسية هي نفسها كما رأينا في الدراسات السابقة من j00ro ، taviso ، وغيرها. تحتوي بعض أسماء حالات WNF على بنيات بيانات مشفرة مع مشاكل الحشو و / أو المحاذاة المختلفة. في بعض الحالات ، تسرب الذاكرة غير مهيأ.
من المترجم : ترجمة الجزء التمهيدي من المستند Detectioning Kernel Memory Disclosure مع x86 Emulation and Taint Tracking من Mateusz Jurczyk aka j00ro .
اكتشاف أسماء الدول والأذونات
الطريقة الأولى كانت اكتشاف جميع أسماء الحالات الممكنة التي يمكن معالجتها بشكل ضار. بالنسبة إلى الأسماء المعروفة والدائمة والمستمرة ، يكون التعداد ممكنًا عن طريق تعداد مفاتيح التسجيل. ثم يمكن مقارنة القيم التي تم العثور عليها مع معرفات ودية (هناك العديد من الأماكن التي يمكنك العثور عليها :))
ثم يمكننا أيضًا النظر إلى واصف الأمان في السجل (هذا هو أول شيء في مخزن البيانات المؤقت). واصف الأمان ليس قانونيًا: ليس به مالك ومجموعة ، لذلك فهو غير صالح تقنيًا. ولكن لا توجد مشكلة في استبدال مالك ومجموعة مزيفين لإصلاح واصف الأمان.
الكشف عن أسماء الحالات المؤقتة وأذوناتها
ولكن مع الأسماء المؤقتة ، لن تعمل الحيل الموضحة أعلاه: فهي ليست في السجل. ويخزن النواة فقط هياكل البيانات الخاصة بهم (! Wnf) في الذاكرة. لكن الأسماء المؤقتة ليست في الواقع من الصعب للغاية استخدام القوة الغاشمة:
- الإصدار يهم دائما 1
- دائمًا ما يهم WnfTporaryStateName
- يتم دائمًا مسح العلامة الدائمة (لا يمكن أن يحتوي اسم الحالة المؤقتة على بيانات دائمة)
- يمكن أن يأخذ النطاق (النطاق) إحدى القيم الأربعة
نعم ، ولكن الرقم التسلسلي المتبقي هو 51 بت! في الواقع ... ولكن لا تنس أن الأرقام التسلسلية تنمو رتابة. وبالنسبة للأسماء المؤقتة ، تتم إعادة تعيين التسلسل إلى 0 في كل عملية تمهيد. بشكل تقليدي ، يمكنك أن تأخذ نافذة تحتوي على مليون رقم تسلسلي: في حلقة ، تحقق من وجود كل اسم (يبدأ من 0) عن طريق الاتصال بـ ZwQueryWnfStateNameInformation مع فئة المعلومات المطلوبة WnfInfoStateNameExist (بالنظر إلى أن خطأ الوصول يشير أيضًا إلى وجود اسم). إذا لم يكن هناك مليون اسم آخر ، فيمكنك إيقاف البحث.
يتم تخزين واصفات أمان الاسم المؤقت (مثل بيانات الاسم المؤقتة الأخرى) في kernel. لذلك ، فإن الطريقة الوحيدة لطلبها هي! Wnf extension عند تصحيح وضع kernel. لكن يمكننا:
- توصل إلى استنتاج حول أذونات القراءة عند محاولة قراءة البيانات.
- لاستنتاج أن التسجيل مسموح به من خلال محاولة كتابة البيانات. لكن تجدر الإشارة إلى أن الكتابة الناجحة حتى 0 بايت تدمر البيانات التي لم يتمكن المستهلك الحقيقي من الحصول عليها بعد. ومرة أخرى ، هناك خدعة: يمكننا تطبيق ختم التغيير المناسب. نحن نحاول الكتابة باستخدام التسمية 0xFFFFFFFF: يتم التحقق من التسمية بعد التحقق من الوصول ، وبالتالي ، فإن قيمة الخطأ ينتج عنها تسرب إذن الكتابة.
هذا لا يعطينا واصف أمان كامل ، ولكن من خلال تشغيل الكود بامتيازات مختلفة ، يمكننا الحصول على فكرة عن القيود المفروضة على حسابات النظام المختلفة (Low IL / User / Admin / SYSTEM).
قائمة المشتركين
في بنية WNF_PROCESS_CONTEXT ، يكون أحد الحقول هو رأس القائمة (LIST_ENTRY) لجميع اشتراكات هذه العملية. كل اشتراك هو نسخة منفصلة من WNF_SUBSCRIPTION.
مشتركو وضع Kernel مملوكون بشكل أساسي لعملية النظام. يمكننا استخدام الأمر! List debugger لتفريغ المعالجات والمعلمات الخاصة بها المسجلة في عملية نظام WNF_SUBSCRIPTION. تجدر الإشارة إلى أنه في بعض الحالات ، يتم استخدام أداة تجميع الأحداث (CEA.SYS) ، والتي تخفي عناوين رد الاتصال الحقيقية في بنية السياق الخاصة بها.
يمكننا تكرار هذا الأسلوب في عمليات وضع المستخدم ، لكن عنوان رد الاتصال سيكون فارغًا ، حيث إنهم مشتركون في وضع المستخدم. لذلك ، نحتاج إلى الانضمام إلى مساحة المستخدم الخاصة بالعملية ، والحصول على جدول RtlpWnfProcessSubscriptions ، ثم تفريغ قائمة مثيلات WNF_USER_SUBSCRIPTION ، كل منها يحتوي بالفعل على عنوان رد الاتصال. لسوء الحظ ، هذه الشخصية ثابتة ، مما يعني أنها ليست بأحرف مفتوحة ، ولكن يمكن العثور عليها عن طريق التفكيك. ومرة أخرى يجدر الانتباه (عن طريق القياس مع وضع kernel CEA.SYS) أن العديد من معالجات وضع المستخدم يستخدم مجمع الحدث (EventAggregation.dll) ، الذي يخزن رد الاتصال في السياق الخاص به.
أسماء حالة مثيرة للاهتمام وحساسة WNF
يقدم هذا القسم بعض الأمثلة المثيرة للاهتمام حول كيفية كشف بعض أسماء حالات WNF عن معلومات النظام.
تحديد حالة النظام وسلوك المستخدم باستخدام WNF
يمكن استخدام بعض معرفات WNF للحصول على معلومات حول حالة الجهاز التي تهمك:
- WNF_WIFI_CONNECTION_STATUS - الحالة اللاسلكية
- WNF_BLTH_BLUETOOTH_STATUS - بالمثل ، ولكن بالنسبة إلى Bluetooth (أيضًا WNF_TETH_TETHERING_STATE)
- WNF_UBPM_POWER_SOURCE - يعرض مصدر الطاقة (البطارية أو محول الطاقة)
- WNF_SEB_BATTERY_LEVEL - يحتوي على مستوى البطارية
- WNF_CELL_ * - يحتوي Windows Phone على معلومات حول: الشبكة أو الرقم أو قوة الإشارة أو EDGE أو 3G ، ...
WNF :
- WNF_AUDC_CAPTURE/RENDER — ( PID), /
- WNF_TKBN_TOUCH_EVENT — ,
- WNF_SEB_USER_PRESENT/WNF_SEB_USER_PRESENCE_CHANGED — Windows
API
, API , API , , /. WNF . , , WNF .
: WNF_SHEL_(DESKTOP)_APPLICATION_(STARTED/TERMINATED) modern- ( , ) DCOM, Win32. — ShellExecute: Explorer, cmd.exe, ...
, WNF API , :
- WNF_SHEL_LOCKSCREEN_ACTIVE —
- WNF_EDGE_LAST_NAVIGATED_HOST — URL, ( ) Edge
WNF
WNF, . : WNF_FSRL_OPLOCK_BREAK — , (/), PID' !
WNF , . : WNF_SHEL_DDC_(WNS/SMS)_COMMAND – 4 , .
, WNF, . : WNF_CERT_FLUSH_CACHE_TRIGGER ( ), WNF_BOOT_MEMORY_PARTITIONS_RESTORE, WNF_RTDS_RPC_INTERFACE_TRIGGER_CHANGED, ...
WNF
:
- WriteProcessMemory —
- ( ) —
- (Atom) —
- — , WM_COPYDATA DDE,
- GUI — ( ) ,
WNF :
- WNF, (, )
- Rtl/ZwQueryWnfStateData WNF
, :
- APC s
- (Remote Threads)
- (Changing Thread Context)
- " window long " — , ,
WNF_USER_SUBSCRIPTION ( WNF_NAME_SUBSCRIPTION, RtlpWnfProcessSubscriptions). ( CFG ), ( 5 6 ).
, : , , , -.
WNF SEB_, ( S ystem E vents B roker). SystemEventsBrokerServer.dll SystemEventsBrokerClient.dll API . , SEB SEB, .
CEA.SYS EventAggregation.dll. " " (Event Aggregation Library), , : , , WNF , . WNF, . .
: .
, Windows Notification Facility Alex' Gabrielle. ( ) redp .

WNF ( ) wincheck . , Gabrielle Viala , redp, : http://redplait.blogspot.com/search/label/wnf .
PoC ( github ) explorer ( — notepad). modexp : Callback WNF_USER_SUBSCRIPTION. :
- explorer.exe
- WNF_USER_SUBSCRIPTION
- RWX- , WriteProcessMemory (, VirtualAllocEx + WriteProcessMemory)
- WNF_USER_SUBSCRIPTION ( WriteProcessMemory)
- ntdll!NtUpdateWnfStateData(...) ,
- WNF_USER_SUBSCRIPTION