
CVE-2026-42978 — Windows Push Notifications (WpnService) में Use-After-Free race condition. पैच डिफ, मूल कारण विश्लेषण, TOCTOU लैब, Sysmon/ETW डिटेक्शन नियम।
रेस कंडीशन Windows पुश नोटिफिकेशन सेवा (WpnService) में जो NT AUTHORITY\SYSTEM के रूप में चलती है। स्थानीय पहुँच वाला हमलावर प्लेटफ़ॉर्म शटडाउन के दौरान use-after-free ट्रिगर कर सकता है और संभावित रूप से विशेषाधिकार बढ़ा सकता है।
WpnService Windows पुश नोटिफिकेशन सेवा है। यह svchost.exe -k netsvcs -p के अंदर LocalSystem के रूप में सेशन 0 में चलती है। सभी सूचना वितरण — टोस्ट, टाइल्स, बैज — इसके माध्यम से जाते हैं।
कमजोरी wpncore.dll में है, विशेष रूप से PresentationEndpointFacade वर्ग में। यह वर्ग सभी सूचना API कॉल (टोस्ट वितरण, सेशन प्रबंधन, सेटिंग्स क्वेरी, आदि) को लपेटता है और PresentationEndpointImpl को कार्य सौंपता है।
बग: प्लेटफ़ॉर्म शटडाउन के दौरान, NotificationPlatform ऑब्जेक्ट नष्ट हो जाता है। लेकिन Facade विधियाँ जाँच नहीं करतीं कि शटडाउन चल रहा है या नहीं — वे प्लेटफ़ॉर्म के लिए एक पॉइंटर पकड़ लेती हैं, प्लेटफ़ॉर्म को शटडाउन थ्रेड द्वारा मुक्त कर दिया जाता है, और Facade एक डैंगलिंग पॉइंटर का उपयोग करता है। क्लासिक use-after-free रेस।
// PresentationEndpointFacade::ToastUnblockAll — कमजोर
long ToastUnblockAll(PresentationEndpointFacade *this) {
// कोई लॉक नहीं। कोई शटडाउन जाँच नहीं। बस प्लेटफ़ॉर्म पॉइंटर पकड़ो और चलो।
NotificationPlatformHandle::Get(this + 0x50);
if (platform == NULL) Throw_Hr(...);
// यदि शटडाउन यहीं पर प्लेटफ़ॉर्म को मुक्त कर दे — use-after-free
return PresentationEndpointImpl::UnblockToastsForEachApp(...);
}
Ghidra: कमजोर ToastUnblockAll — प्लेटफ़ॉर्म तक पहुँचने से पहले कोई सिंक्रनाइज़ेशन नहीं
// PresentationEndpointFacade::ToastUnblockAll — पैच किया गया
long ToastUnblockAll(PresentationEndpointFacade *this) {
if (Feature_4097557817::IsEnabled()) {
AcquireSRWLockShared(&Wns::s_platformLock); // 1. साझा लॉक
if (Wns::s_platformShutdown) // 2. शटडाउन गार्ड
Throw_Hr(E_APPLICATION_EXITING);
NotificationPlatformHandle::Get(this + 0x50);
// ... कार्य करें ...
ReleaseSRWLockShared(&Wns::s_platformLock); // 3. RAII रिलीज़
} else {
// फीचर फ्लैग बंद — रोलबैक के लिए पुराना व्यवहार संरक्षित
}
}
फिक्स में तीन चीजें जोड़ी गई हैं:
AcquireSRWLockShared — साझा रीडर्स-राइटर्स लॉक। कई API कॉल एक साथ चल सकते हैं, लेकिन शटडाउन एक एक्सक्लूसिव लॉक लेता है और उन सभी को ब्लॉक करता है।s_platformShutdown जाँच — यदि शटडाउन पहले ही शुरू हो चुका है, तो E_APPLICATION_EXITING के साथ तुरंत बाहर निकलें।wil::unique_storage रैपर में रखा जाता है, इसलिए यह अपवाद फेंके जाने पर भी जारी हो जाता है।फीचर फ्लैग Feature_4097557817 WIL (Windows Internal Library) के माध्यम से चरणबद्ध रोलआउट के लिए है। यह माइक्रोसॉफ्ट को फिक्स को धीरे-धीरे सक्षम करने और यदि कुछ टूटता है तो इसे अक्षम करने देता है।
यह एक-फंक्शन बग नहीं है। wpncore.dll में 49 फंक्शन में समान लॉक+गार्ड पैटर्न जोड़ा गया था:
| श्रेणी | फंक्शन |
|---|---|
| टोस्ट संचालन | ToastUnblockAll, ToastCreateSession, ToastCloseSession, ToastRequestAllNotifications, ToastSuppress |
| टाइल संचालन | TileCreateSession, TileCloseSession, TileRequestResourceForeground |
| पंजीकरण | RegisterApplication, UnregisterApplication, RegisterHandler, UpdateRegistration, RegisterSystemApplication |
| सेटिंग्स | ChangeAppSetting, QueryAppSetting, QueryGlobalSetting, RegisterSettingCallback, UnregisterSettingCallback |
| वितरण | Deliver, GetPayloadForNotificationId, Submit, PostScheduledNotification |
| क्वेरी | GetRegisteredHandler, GetRegisteredHandlersFromParent, GetSettingsFromHandler, GetAssetsFromHandler |
प्रत्येक PresentationEndpointFacade::* विधि जो प्लेटफ़ॉर्म को छूती है, उसे वही फिक्स मिला। अंतर्निहित PresentationEndpointImpl::* विधियाँ अपरिवर्तित हैं — समस्या केवल फ़ेसेड परत पर थी।
WpnService SYSTEM के रूप में चलता है। यदि रेस जीत ली जाती है:
NotificationPlatform ऑब्जेक्ट की मेमोरी को पुनः प्राप्त किया जा सकता है और हमलावर-नियंत्रित डेटा (हीप स्प्रे) से भरा जा सकता हैNT AUTHORITY\SYSTEM के रूप में कोड निष्पादनवास्तविक शोषण — हीप स्प्रे, vtable हाइजैकिंग, कोड निष्पादन प्राप्त करना — इस शोध के दायरे से बाहर है। यह रिपॉजिटरी मूल कारण को समझने और पता लगाने के निर्माण पर केंद्रित है।
lab/ निर्देशिका में एक स्वतंत्र C डेमो है जो WpnService को छुए बिना बग की श्रेणी को पुन: उत्पन्न करता है। यह WpnService के समान नामित पाइप + साझा मेमोरी आर्किटेक्चर का उपयोग करता है।
यह कैसे काम करता है:
vulnerable_service.exe साझा मेमोरी से एक संदेश की लंबाई पढ़ता है, इसे मान्य करता है, 50ms के लिए सोता है, फिर लंबाई को फिर से पढ़ता है (डबल-फ़ेच)।race_attacker.exe एक सुरक्षित लंबाई सेट करता है, सेवा को ट्रिगर करता है, फिर तुरंत साझा मेमोरी को एक ओवरफ्लो मान पर फ्लिप करता है।vulnerable_service.exe --patched चलाकर फिक्स देखें: एक स्थानीय वेरिएबल में सिंगल-फ़ेच कैप्चर।
बाएँ: सेवा रेस का पता लगाती है (5/5)। दाएँ: हमलावर साझा मेमोरी मान फ्लिप कर रहा है।
GCC (MinGW) आवश्यक है। lab/ निर्देशिका से:
build.bat
टर्मिनल 1:
vulnerable_service.exe
टर्मिनल 2:
race_attacker.exe 5
फिर vulnerable_service.exe --patched से तुलना करें — समान हमला, शून्य रेस का पता चला।
detection/etw_wpn_monitor.ps1)पावरशेल स्क्रिप्ट जो 7 संकेतकों की जाँच करती है:
powershell -ExecutionPolicy Bypass .\detection\etw_wpn_monitor.ps1
ETW मॉनिटर: WpnService चल रहा है (PID 6432), कोई क्रैश नहीं, 100 इवेंट/घंटा, सिस्टम पैच किया गया
detection/sysmon_wpn_race_detect.xml)निरंतर निगरानी के लिए छह नियम समूह:
| नियम | यह क्या पकड़ता है |
|---|---|
WPN_EoP_ChildProcess | svchost (netsvcs) cmd/powershell/wscript का जन्म |
WPN_PipeAccess | WPN-संबंधित नामित पाइपों से कनेक्शन |
WPN_FileCreation | सूचना डेटा निर्देशिकाओं में फ़ाइल निर्माण |
WPN_RegistryTampering | PushNotifications कुंजियों में रजिस्ट्री लेखन |
WPN_ProcessAccess | svchost के लिए PROCESS_ALL_ACCESS हैंडल |
WPN_ThreadInjection | svchost में CreateRemoteThread |