ब्लूज़ के लिए शिकार – डब्ल्यूएसएल योजना 9 प्रोटोकॉल बीएसओडी

लिनक्स प्लान 9 प्रोटोकॉल रिसर्च ओवरव्यू के लिए विंडोज सबसिस्टम

यह लिनक्स (WSL) कार्यान्वयन के लिए विंडोज सबसिस्टम पर McAfee शोध श्रंखला त्रयी में अंतिम ब्लॉग है – द ट्विन जर्नी (भाग 1) और नॉक, नॉक-हूज (पार्ट 2) देखें। Microsoft P9 सर्वर को दुर्भावनापूर्ण P9 (योजना 9 फ़ाइल सिस्टम प्रोटोकॉल) सर्वर से अपहृत किया जा सकता है, जब पिछले शोध ने फ़ाइल चोरी के हमलों पर चर्चा की। विंडोज 10 संस्करण 1903 के बाद से, पी 9 प्रोटोकॉल का उपयोग करके विंडोज से लिनक्स फाइलों तक पहुंचना संभव है। डब्लूएस 10 ऑपरेटिंग सिस्टम डब्ल्यूएसएल इंस्टॉल के हिस्से के रूप में पी 9 सर्वर के साथ आता है ताकि यह लिनक्स फाइल सिस्टम के साथ संवाद कर सके। इस शोध में हम विंडोज कर्नेल के भीतर P9 प्रोटोकॉल कार्यान्वयन का पता लगाते हैं और क्या हम दुर्भावनापूर्ण P9 सर्वर से इसमें कोड निष्पादित कर सकते हैं। हमने Microsoft P9 सर्वर को हाईजैक करके एक दुर्भावनापूर्ण P9 सर्वर बनाया और इसे कोड के साथ बदलकर हम नियंत्रित कर सकते हैं।

एक विशिष्ट हमले के परिदृश्य में, हमें पता चला कि अगर WSL को विंडोज 10 पर सक्षम किया जाता है, तो एक गैर-विशेषाधिकार प्राप्त स्थानीय हमलावर WSL P9 संचार चैनल को ठिकाने लगाने के लिए सेवा से वंचित कर सकता है (DoS) या ब्लू स्क्रीन ऑफ डेथ (BSOD) विंडोज कर्नेल। इस भेद्यता के कारण विंडोज कर्नेल के भीतर विशेषाधिकार (ईओपी) की वृद्धि को प्राप्त करना संभव नहीं है; यदि Microsoft Windows कर्नेल द्वारा विकृत P9 सर्वर संचार पैकेट प्राप्त कर लेता है, तो BSOD अपने वैध असफल प्रवाह के भीतर Microsoft द्वारा डिज़ाइन किया गया प्रतीत होता है। एक गैर-विशेषाधिकार प्राप्त उपयोगकर्ता को स्थानीय या दूरस्थ दृष्टिकोण से, विंडोज कर्नेल को बीएसओडी करने में सक्षम नहीं होना चाहिए। यदि WSL सक्षम नहीं है (Windows 10 पर डिफ़ॉल्ट रूप से अक्षम), तो भी हमले को अंजाम दिया जा सकता है लेकिन हमलावर को WSL को पूर्व-आवश्यकता के रूप में सक्षम करने के लिए एक विशेषाधिकार प्राप्त उपयोगकर्ता होने की आवश्यकता है।

हाल ही में आरडीपी और एसएमबी प्रोटोकॉल के भीतर ब्लूकीस्ट और एसएमबीएचहोस्ट के रूप में कुछ महत्वपूर्ण, चिंताजनक प्रोटोकॉल कमजोरियां आई हैं। दूरस्थ रूप से शोषक भेद्यताएँ बहुत अधिक जोखिम वाली होती हैं यदि वे खराब होती हैं क्योंकि वे बिना किसी उपयोगकर्ता सहभागिता के सिस्टम में फैल सकती हैं। स्थानीय भेद्यता कम जोखिम है क्योंकि एक हमलावर को पहले सिस्टम पर उपस्थिति होनी चाहिए; इस स्थिति में उनके पास दुर्भावनापूर्ण P9 सर्वर निष्पादित होना चाहिए। P9 प्रोटोकॉल कार्यान्वयन स्थानीय रूप से विंडोज कर्नेल के भीतर चलता है, इसलिए, अधिकांश स्थानीय भेद्यता शिकार के साथ, एक भेद्यता को खोजने के लिए है जो विशेषाधिकार (ईओपी) को बढ़ाने की अनुमति देता है।

इस ब्लॉग में हम प्रोटोकॉल कार्यान्वयन और भेद्यता शिकार प्रक्रिया में एक गहरा गोता लगाते हैं। इस शोध से WSL उपयोगकर्ताओं के लिए कोई जोखिम नहीं है, जिसे Microsoft द्वारा साझा और मान्य किया गया है। हमें उम्मीद है कि यह शोध डब्ल्यूएसएल पी 9 संचार स्टैक की समझ को बेहतर बनाने में मदद करेगा और अतिरिक्त अनुसंधान स्टैक को और अधिक उपयोगी होगा।

डब्ल्यूएसएल पर कुछ कारनामे हुए हैं जैसे कि यहां और यहां लेकिन इसके अलावा P9 प्रोटोकॉल कार्यान्वयन का कोई दस्तावेजी शोध नहीं हुआ है।

P9 प्रोटोकॉल अवलोकन

प्लान 9 फाइल सिस्टम प्रोटोकॉल सर्वर क्लाइंट को फाइल बनाने, हटाने, पढ़ने और लिखने के लिए फाइल सिस्टम को नेविगेट करने की अनुमति देता है। क्लाइंट सर्वर को अनुरोध (टी-संदेश) भेजता है और सर्वर आर-संदेश के साथ प्रतिक्रिया करता है। P9 प्रोटोकॉल में एक हेडर है जिसमें आकार, प्रकार और टैग फ़ील्ड शामिल हैं, जो क्लाइंट से अनुरोध के आधार पर एक संदेश प्रकार फ़ील्ड द्वारा पीछा किया जाता है। सर्वर द्वारा भेजे गए आर-संदेश प्रकार को क्लाइंट से शुरू किए गए टी-संदेश प्रकार से मेल खाना चाहिए। डेटा ट्रांसफर के लिए अधिकतम कनेक्शन का आकार क्लाइंट द्वारा कनेक्शन सेटअप के दौरान तय किया जाता है; नीचे हमारे विश्लेषण में, यह 0x10000 बाइट्स है।

संदेश प्रकार संघ के बाद P9 प्रोटोकॉल हेडर (हमने केवल P9 संदेश प्रकारों के सबसेट को शामिल किया है जो भेद्यता अनुसंधान के लिए रुचि रखते हैं):

संरचना P9Packet {

u32 आकार;

u8 प्रकार;

u16 टैग;

संघ {

संरचना p9_rversion तोड़फोड़;

संरचना p9_rread rread;

संरचना p9_rreaddir rreaddir;

संरचना p9_rwalk rwalk;

} यू

} P9Packet

P9 T-message और संबंधित R-message नंबर उन प्रकारों के लिए हैं जिनमें हम रुचि रखते हैं (R-संदेश हमेशा T-message 1) है:

एनम p9_msg_t {

P9_TREADDIR = 40,

P9_RADADIR = 41,

P9_TVERSION = 100,

P9_RVERSION = 101,

P9_TWALK = 110,

P9_RWALK = 111,

P9_TREAD = 116,

P9_RREAD = 117,

}

संदेश प्रकार परत पर, जो P9 प्रोटोकॉल शीर्षलेख का अनुसरण करता है, आप नीचे हाइलाइट किए गए फ़ील्ड देख सकते हैं, जो चर आकार के हैं:

संरचना p9_rwalk {

यू 16 nwqid;

संरचना p9_qid wqids[[P9_MAXWELEM];

}

संरचना p9_rread {

u32 गिनती;

u8 *डेटा;

}

संरचना p9_rreaddir {

u32 गिनती;

u8 *डेटा;

}

संरचना p9_rversion {

u32 msize;

संरचना p9_str संस्करण;

}

संरचना p9_str {

यू 16 लेन;

चार *str;

}

P9 प्रोटोकॉल के पैकेट संरचना के आधार पर हमें संदेश प्रकार भ्रम और स्मृति भ्रष्टाचार कमजोरियों के लिए शिकार करने की आवश्यकता है जैसे कि रीड / राइट से बाहर।

तो, एक पैकेट संरचना स्मृति में क्या दिखेगी? चित्रा 1 WinDbg से प्रोटोकॉल हेडर और संदेश प्रकार मेमोरी लेआउट दिखाता है। संदेश का आकार (msize) 0x10000 के लिए बातचीत की है और संस्करण स्ट्रिंग “9P2000.W” है।

आकृति 1। P9 पैकेट rversion संदेश प्रकार के लिए

Windows WSL P9 संचार स्टैक और डेटा संरचनाएँ

चित्र 2। WSL के भीतर विंडोज प्लान 9 फाइल सिस्टम प्रोटोकॉल कार्यान्वयन

P9rdr.sys नेटवर्क मिनी-रिडायरेक्टर ड्रायवर, R9RegisterMinirdad API का उपयोग करते हुए p9rdr DriverEntry रूटीन के भाग के रूप में Redirected Drive Buffering सबसिस्टम (RDBSS) के साथ “\ Device \ P9Rdr” डिवाइस को पंजीकृत करता है। इस पंजीकरण के दौरान, निम्नलिखित P9 API या ड्राइवर रूट RDBSS के संपर्क में हैं:

P9NotImplemented

P9Start

P9Stop

P9DevFcbXXXControlFile

P9CreateSrvCall

P9CreateVNetRoot

P9ExtractNetRootName

P9FinalizeSrvCall

P9FinalizeVNetRoot

P9Create

P9CheckForCollapsibleOpen

P9CleanupFobx

P9CloseSrvOpen

P9ForceClosed

P9ExtendFile

P9Flush

P9QueryDirectoryInfo

P9QueryVolumeInfo

P9QueryFileInfo

P9SetFileInfo

P9IsValidDirectory

P9Read

P9Write

DeviceIoControl API का उपयोग करके p9rdr ड्राइवर सीधे उपयोगकर्ता मोड से सुलभ नहीं है और सभी कॉल RDBSS के माध्यम से जाने चाहिए।

जैसा कि चित्र 2 में देखा गया है, जब कोई उपयोगकर्ता एक्सप्लोरर से WS के शेयर “\ wsl $” पर नेविगेट करता है, आरडीबीएसएस चालक पहले पंजीकृत एपीआई के माध्यम से पी 9 चालक में कॉल करता है।

DIOD एक फ़ाइल सर्वर कार्यान्वयन है, जिसे हमने “दुर्भावनापूर्ण” P9 सर्वर के रूप में संशोधित किया है, जहाँ हम स्क्वाटिंग अटैक के रूप में विंडोज़ ओएस से पहले “fsserver” सॉकेट नाम का दावा करते हैं। एक बार जब हमने Microsoft P9 सर्वर को DIOD सर्वर से बदल दिया, तो हमने “np_req_respond” फ़ंक्शन (फ़ज़िंग बाधाओं की व्याख्या की) को संशोधित किया ताकि हम Windows कर्नेल के लिए दुर्भावनापूर्ण प्रतिक्रियाएँ भेजने के लिए P9 पैकेटों को नियंत्रित कर सकें। हमारे दुर्भावनापूर्ण P9 सर्वर और सॉकेट अपहरण को यहां विस्तार से समझाया गया है।

तो अब हम जानते हैं कि एक्सप्लोरर से डेटा P9 ड्राइवर तक कैसे जाता है लेकिन P9 ड्राइवर दुर्भावनापूर्ण P9 सर्वर के साथ कैसे संवाद करता है? वे AF_UNIX सॉकेट पर संचार करते हैं।

P9 ड्राइवर के भीतर डेटा प्रवाह को नियंत्रित करने के लिए P9Client और P9Exchange नामक दो महत्वपूर्ण डेटा संरचनाएं उपयोग की जाती हैं।

P9Client और P9Exchange डेटा संरचनाएँ, जब इस शोध के लिए प्रासंगिक फ़ील्ड्स के लिए रिवर्स इंजीनियरिंग किया जाता है, तो निम्न की तरह देखें (इस विश्लेषण के लिए प्रासंगिक फ़ील्ड को संरेखण के लिए UINT64 के रूप में लेबल किया गया है):

टाइप्डिफ़ संरचना P9Client {
PVOID * WskTransport_vftable
PVOID * GlobalDevice
UNINT64 RunRef
WskSocket * WskData
UINT64
UINT64
UINT_PTR
PVOID * MidExchangeMgr_vftable
PRDBSS_DEVICE_OBJECT * RDBSS
UINT64
PVOID ** WskTransport_vftable
PVOID ** MidExchangeMgr_vftable
P9Packet * P9PacketStart
UINT64 मैक्सकॉन्क्शन
UINT64 Rmessage_size
P9Packet * P9PacketEnd
UINT_PTR
UINT64
UINT64
UINT_PTR
UINT64
UINT64
PVOID * सत्र_ReconnectCallback
PVOID ** WskTransport_vftable
UINT64
UINT_PTR
UINT_PTR
UINT64
UINT_PTR
UINT64
UINT64
UINT64
} P9Client

Win9bg में P9Client डेटा संरचना मेमोरी लेआउट:

टाइप्डिफ़ संरचना P9Exchange {
UINT64
UINT64
P9Client * P9Client
UINT64 Tmessage_type
UINT64
UINT_PTR
पीवीओआईडी * लाम्बडा_पीटीआर 1
पीवीओआईडी * लाम्बडा_पीटीआर 2
PRX_CONTEXT * RxContextUINT64 Tmessage_size
UINT64
UINT64
UINT64
UINT64
UINT64
UINT64
} P9Exchange

WinDbg में P9Exchange डेटा संरचना लेआउट:

P9 सर्वर के साथ संवाद करने के लिए, P9 ड्राइवर Winsock कर्नेल (WSK) से डेटा प्राप्त करने के लिए I / O अनुरोध पैकेट (IRP) बनाता है। ध्यान देने वाली एक महत्वपूर्ण बात यह है कि P9 सर्वर और विंडोज कर्नेल P9 क्लाइंट के बीच पारित डेटा को होल्ड करने के लिए उपयोग की जाने वाली मेमोरी डिस्क्रिप्टर लिस्ट (MDL) 0x10000 बाइट्स (पहले उल्लेखित अधिकतम कनेक्शन आकार) है।

आभासी लंबे WskTransport :: प्राप्त () {

UNINT64 MaxConnectionSize = 0x10000;

P9_IRP_OBJECT = RxCeAllocateIrpWithMDL (2, 0, 0i64);

P9_MDL = IoAllocateMdl (P9Client-> P9PacketStart, मैक्सकॉन्सेक्शनाइज़, 0, 0, 0i64);
शून्य MmBuildMdlForNonPagedPool (P9_MDL);
P9_IRP_OBJECT-> IoStackLocation-> पैरामीटर-> MDL = & P9_MDL;

P9_IRP_OBJECT-> IoStackLocation-> पैरामीटर-> P9Client = & P5Client;

P9_IRP_OBJECT-> IoStackLocation-> पैरामीटर-> डेटापाथ = & P9Client :: ReceiveCallback;
P9_IRP_OBJECT-> IoStackLocation-> पूर्ण समापन Routine = p9fs :: WskTransport :: SendReceiveComplete
WskProAPIReceive (* WskSocket, * P9_MDL, 0, * P9_IRP_OBJECT);
}

MD9 P9Client डेटा संरचना के भीतर P9PacketStart फ़ील्ड पते पर मैप किया जाता है।

IRP पूरा होने पर, WskTransport :: SendReceiveComplete दिनचर्या को सर्वर से P9 पैकेट प्रतिक्रिया को संसाधित करने के लिए IRP से P9Client संरचना को पुनः प्राप्त करने के लिए कहा जाता है:

int static WskTransport :: SendreceiveComplete (IRP * P9_IRP_OBJECT) {

P9Client = & P9_IRP_OBJECT-> IoStackLocation-> पैरामीटर-> P5Client;

P9Client :: ReceiveCallback (P9Client * P9Client);

}

P9Client डेटा संरचना का उपयोग R-संदेश डेटा प्राप्त करने के लिए IRP के भीतर किया जाता है लेकिन P9Exchange डेटा संरचना का उद्देश्य क्या है?

  1. जब पी 9 ड्राइवर सर्वर को एक टी-संदेश भेजता है, तो उसे एक एक्सचेंज बनाना होगा ताकि वह भेजे गए संदेश प्रकार (टी-संदेश) के बीच की स्थिति को ट्रैक कर सके और यह सर्वर (आर-संदेश) द्वारा वापस आए।
  2. इसमें विशिष्ट संदेश प्रकार पर निष्पादित करने के लिए लंबो कार्य शामिल हैं। P9Exchange डेटा संरचना के भीतर Tmessage_type फ़ील्ड यह सुनिश्चित करती है कि सर्वर केवल उसी T-संदेश प्रकार को R-संदेश भेज सकता है जो उसे P9 ड्राइवर से प्राप्त हुआ है।
  3. PRX_CONTEXT * RBContext संरचना का उपयोग RDBSS ड्राइवर के माध्यम से एक्सप्लोरर और p9rdr ड्राइवर के बीच डेटा स्थानांतरित करने के लिए किया जाता है।

एक वाल्क टी-संदेश का प्रवाह नीचे देखा जा सकता है:

P9Client :: CreateExchange फ़ंक्शन के भीतर, MidExchangeManager :: RegisterExchange, P9Exchange डेटा संरचना को RDBSS के साथ मल्टीप्लेक्स आईडी (MID) का उपयोग करके कंसर्ट सर्वर और क्लाइंट अनुरोधों के बीच अंतर करने के लिए पंजीकृत करने के लिए जिम्मेदार है।

MidExchangeManager :: RegisterExchange (* P9Client, * P9Exchange) {

NTSTATUS RxAssociateContextWithMid (PRX_MID_ATLAS P9Client-> RDBSS, PVOID P9Exchange, PUSHORT NewMid);

}

P9Client और P9Exchange डेटा संरचनाओं के भीतर महत्वपूर्ण क्षेत्र जो हम विश्लेषण के दौरान आगे चर्चा करेंगे:

  1. PClient-> MaxConnectionSize – कनेक्शन की शुरुआत में सेट करें और एक हमलावर द्वारा नियंत्रित नहीं किया जा सकता है
  2. P9Client-> P9PacketStart – P9 पैकेट को इंगित करता है और एक हमलावर द्वारा पूरी तरह से नियंत्रित किया जा सकता है
  3. P9Client-> Rmessage_size –can एक हमलावर द्वारा पूरी तरह से नियंत्रित किया जा सकता है
  4. P9Exchange-> Tmessage_type – T- संदेश निर्माण के दौरान सेट और एक हमलावर द्वारा नियंत्रित नहीं किया जा सकता है
  5. P9Exchange-> RxContext – RD9SS से एक्सप्लोरर के माध्यम से P9 ड्राइवर से डेटा पास करता था

अब जब हम जानते हैं कि प्रोटोकॉल विंडोज कर्नेल के भीतर कैसे काम करता है, तो अगला चरण भेद्यता शिकार है।

विंडोज कर्नेल P9 सर्वर भेद्यता शिकार

P9 पैकेट प्रोसेसिंग लॉजिक

दुर्भावनापूर्ण दृष्टिकोण से हम दुर्भावनापूर्ण P9 सर्वर से ट्रैफ़िक पार्स करने के लिए जिम्मेदार p9rdr.sys के भीतर विंडोज कर्नेल लॉजिक का ऑडिट करना चाहते हैं। चित्र 3 P9 पैकेट के स्रोत और सिंक को दर्शाता है, या जहाँ P9rdr चालक के भीतर पैकेट प्रसंस्करण पूर्ण होता है।

चित्र तीन। P9 प्रोटोकॉल दुर्भावनापूर्ण सर्वर प्रतिक्रिया पार्सिंग के लिए विंडोज कर्नेल प्रोसेसिंग लेयर्स

अब जब हमने P9 प्रोटोकॉल संदेश प्रकार के ब्याज को पार्स करने के लिए कोड की पहचान कर ली है, तो हमें संदेश प्रकार भ्रम और स्मृति भ्रष्टाचार भेद्यता जैसे कि रीड आउट / राइट और ओवरफ्लो के लिए कोड की ऑडिट करने की आवश्यकता है।

फिजूल की बाधाएँ

कई तरह की अड़चनें थीं जो स्वचालित फ़ज़िंग लॉजिक को लागू करना मुश्किल बना देती थीं:

  1. दुर्भावनापूर्ण P9 सर्वर से भेजे गए R- संदेश प्रकार को Windows कर्नेल द्वारा भेजे गए T- संदेश प्रकार से मेल खाना चाहिए
  2. डब्लूएसएल स्टैक की उच्च परतों में टाइमआउट

हालांकि, उपरोक्त चुनौतियां दूर हो सकती हैं, लेकिन चूंकि प्रोटोकॉल अपेक्षाकृत सरल है, इसलिए हमने प्रसंस्करण तर्क सत्यापन को उलटने पर ध्यान केंद्रित करने का निर्णय लिया। प्रसंस्करण तर्क सत्यापन को सत्यापित करने के लिए, हमने प्रोटोकॉल अवलोकन से पहचानी गई चर लंबाई पैकेट फ़ील्ड सीमाओं का परीक्षण करने के लिए दुर्भावनापूर्ण P9 सर्वर के भीतर कुछ मैनुअल फ़ज़िंग क्षमता बनाई।

नीचे एक उदाहरण RREAD R- संदेश प्रकार है जो RREAD T- संदेश के जवाब में एक दुर्भावनापूर्ण P9 पैकेट भेजता है जहां हम गिनती और डेटा चर लंबाई क्षेत्रों को नियंत्रित करते हैं।

srv.c

शून्य

np_req_respond (Npreq * req, Npfcall * rc)

{

NP_ASSERT (rc! = NULL);

xpthread_mutex_lock (और req-> ताला);

u32 गिनती = 0xFFFFFFFF;

Npfcall * fake_rc;

u8 * डेटा = मॉलोक (0xFFF0);

मेमसेट (डेटा, “ए”, 0xFFF0);

अगर ((fake_rc = np_alloc_rread1 (count)))

वापसी NULL;

अगर (fake_rc-> u.rread.data)

memmove (fake_rc-> u.rread.data, data, count);

अगर (आरसी-> टाइप == 0x75) {

fprintf (stderr, “RREAD पैकेट उत्तर”);

req-> rcall = fake_rc;

}

अन्य{

req-> rcall = rc;

}

अगर (req-> राज्य == REQ_NORMAL) {

np_set_tag (req-> rcall, req-> टैग);

np_conn_respond (अनुरोध);

}

xpthread_mutex_unlock (और req-> ताला);

}

सत्यापन जाँच

P9 ड्राइवर को दिया गया डेटा 0x10000 बाइट्स (P9Client-> P9PacketStart) के एक कनेक्शन मेमोरी आवंटन के भीतर समाहित है और अधिकांश प्रोसेसिंग इस मेमोरी एलोकेशन के भीतर की जाती है, दो अपवादों के साथ जहां मेम को P9Client :: FillData और P9Client के भीतर बुलाया जाता है। :: लैम्ब्डा_2275 फ़ंक्शन (नीचे चर्चा की गई)।

P9Exchange डेटा संरचना R- संदेश को उसके संबंधित T- संदेश प्रकार पर ट्रैक करने के बाद से एक संदेश-प्रकार भ्रम की स्थिति संभव नहीं है।

इसके अलावा, P9 ड्राइवर मैसेज रीडर का उपयोग स्टैटिक लेंथ के मैसेज टाइप फील्ड को प्रोसेस करने के लिए करता है। P9Exchange संरचना संदेश प्रकार को संग्रहीत करती है जिसका उपयोग प्रसंस्करण के दौरान एक संदेश के भीतर फ़ील्ड की संख्या निर्धारित करने के लिए किया जाता है।

जब हम P9 पैकेट आकार को नियंत्रित कर सकते हैं तो हम P9Client-> MaxConnectionSize को नियंत्रित नहीं कर सकते हैं जिसका अर्थ है कि 0x10000 से अधिक या इसके बराबर के संदेश हटा दिए जाएंगे।

प्रोटोकॉल के संदेश प्रकार परत के भीतर सभी चर आकार क्षेत्र की जांच P9Packet आकार फ़ील्ड के खिलाफ जाँच की जाती है ताकि यह सुनिश्चित किया जा सके कि दुर्भावनापूर्ण फ़ील्ड 0x10000 कनेक्शन मेमोरी आवंटन के बाहर पढ़ने या लिखने की सीमा के परिणामस्वरूप नहीं होगी।

पहले से पहचाने गए प्रोसेसिंग लॉजिक फ़ंक्शंस रिवर्स प्रकार के थे, जो प्रोटोकॉल के क्षेत्रों पर सत्यापन को समझने के लिए थे, जिसमें संदेश प्रकारों के विचलन, रवॉक और र्रेड के भीतर चर लंबाई फ़ील्ड पर विशेष ध्यान दिया गया था।

आईडीए प्रो में P9Client और P9Exchange डेटा संरचनाओं को आयात करके, पैकेट सत्यापन तर्क को समझने के लिए रिवर्स इंजीनियरिंग प्रक्रिया अपेक्षाकृत सीधे आगे। नीचे दिए गए कार्य सत्यापन को समझने के लिए आवश्यक स्तर पर उलट दिए गए हैं और पूरे फ़ंक्शन कोड आधार के प्रतिनिधि नहीं हैं।

P9Client :: ReceiveCallback पुष्टि करता है कि Rmessage_size 0x0000 के अधिकतम कनेक्शन आकार से अधिक नहीं है

शून्य P9Client :: ReceiveCallback (P9Client * P9Client) {
संरचना p9packet; uint64 MaxConnectionSize; uint64 Rmessage_size; MaxConnectionSize = P9Client-> MaxConnectionSize;
Rmessage_size = P9Client-> Rmessage_size; यदि (MaxConnectionize) {
P9Packet = (स्ट्रक्चर p9packet *) P9Client-> P9PacketSt अगेन; यदि (MaxConnectionSize) < 0 || !P9Packet) terminate(P9Packet);}if (Rmessage_size >= 0 && P9Client-> MaxConnectionSize> = Rmessage_size)
{
P9Client :: हैंडल (* P9Client)
} अन्य{

(P9Packet) को समाप्त;

}

P9Client :: हैंडल – कई हैं स्थानीय DoS जिसके परिणामस्वरूप P9Client-> Rmessage_size और P9Client-> P9PacketEnd-> आकार, जैसे उदाहरण के आधार पर ब्लू स्क्रीन ऑफ डेथ (BSOD) होता है। जब P9Client-> P9PacketEnd-> आकार शून्य समाप्त होता है () कहा जाता है जो बीएसओडी है।

शून्य P9Client :: हैंडल (P9Client * P9Client) {

uint64 P9PacketHeaderSize = 7;

uint64 Rmessage_size = P9Client-> Rmessage_size;

अगर (Rmessage_size> = 7) {
जबकि (1) {

P9PacketEnd = P9Client-> P9PacketEnd;

अगर (P9PacketEnd) ब्रेक;

uint64 P9PacketSize = P9Client-> P9PacketEnd-> आकार;
अगर (P9PacketSize> P9Client-> MaxConnectionSize); HandleIoError ();

अगर (Rmessage_size

अगर (Rmessage_size <4) समाप्त (); // P9 हेडर आकार फ़ील्ड की जाँच पैकेट में मौजूद है

if (Rmessage_size> 5) फास्टफेल (); // P9 हेडर प्रकार फ़ील्ड की जाँच पैकेट में मौजूद है

int message_type = P9PacketEnd-> प्रकार;

अगर (Rmessage_size <7) फास्टफेल (); // P9 हेडर टैग फ़ील्ड की जाँच पैकेट में मौजूद है

uint64 टैग = P9PacketEnd-> टैग;

uint64 P9message_size = P9PacketSize – P9PacketHeaderSize; // संदेश का आकार प्राप्त करना

अगर (Rmessage_size – 7 <0) समाप्त (); // P9 हैडर के बाद संदेश की परत मौजूद है

अगर (Rmessage_size – 7 // बीएसओडी यहां सेट के रूप में P9PacketSize = 0 तो P9message_size के आसपास 7 रैप्स घटाना Rmessage_size से अधिक हो जाता है।

void P9Client :: ProcessReply (P9Client * P9Client, Rmessage_type, tag, & P9message_size);

}

}

अन्य {

P9Client :: FillData ();

}

P9Client :: FillData – हम एक बड़े Rmessage_size के साथ इस फ़ंक्शन को सीमा से बाहर लिखने के लिए बाध्य नहीं कर सकते।

int P9Client :: FillData (P9Client * P9Client) {
uint64 Rmessage_size = P9Client-> Rmessage_size; uint_ptr P9PacketEnd = P9Client-> P9PacketEnd;
uint_ptr P9PacketStart = P9Client-> P9PacketStart, अगर (P9PacketEnd! = P9PacketStart) {
memmove (P9PacketStart, P9PacketEnd, Rmessage_size);
}

ProcessReply P9Exchange डेटा संरचना के भीतर T- संदेश से R- संदेश प्रकार की जाँच करता है।

शून्य P9Client :: ProcessReply (P9Client * P9Client, Rmessage_type, टैग, और P9message_size) {
P9Exchange * P9Exchange = MidExchangeManager :: FindAndRemove (* P9Client, & P9Exchange); यदि (P9Packet-> टैग> 0) {
int message_type_size = GetMessageSize (P9Exchange-> Tmessage_type);
if (P9message_size> = message_type_size) {int rmessage_type = P9Exchange-> MessageType; int rmessage_type = rmessage_type +1;}
अगर (rmessage_type> 72) {
स्विच (संदेश टाइप) {
मामला 100:
P9Client :: ProcessVersionReply (P9Client * P9Client, P9Exchange, और P9message_size);
केस 110:
P9Client :: ProcessWalkreply (Rmessage_type, P9Exchange, & P9message_size);};
}अन्य {
P9Client :: ProcessReadReply (rmessage_type, P9Exchange, & P9message_size);
}}

P9Client :: ProcessReply फ़ंक्शन के दौरान यह MidExchangeManager :: FindAndRemove को R-messages संबंधित T-message से संबंधित P9Exchange डेटा संरचना लाने के लिए कहता है।

MidExchangeManager :: FindAndRemove (* P9Client, और P9Exchange) {

NTSTATUS RxMapAndDissociateMidFromContext (PRX_MID_ATLAS P9Client-> RDBSS_RxContext, USHORT Mid, & P9cchange);

}

ProcessVersionReply क्लाइंट “P92000.L” द्वारा भेजे गए संस्करण की जाँच करता है, जो कि 8 वर्ण है और वापसी पर समान लंबाई की जाँच करता है, इसलिए rversionlen tryString फ़ंक्शन को प्रभावित नहीं करता है।

शून्य P9Client :: ProcessVersionReply (* P9Client, * P9Exchange, और P9message_size) {

char * तोड़फोड़;
int rversionlen = 0;

rversion = P9Client-> P9PacketStart.u.rversion-> संस्करण-> str;

rversionlen = P9Client-> P9PacketStart.u.rversion-> संस्करण-> लेन;

tryString (संदेश करें, और विचलन)

strcmp (Tversion, Rversion);
}

ProcessWalkReply जाँच करता है कि rwalk संरचनाओं की कुल संख्या P9message_size से अधिक नहीं है

शून्य P9Client :: ProcessWalkReply (rmessage_type, * P9Exchange, और P9message_size) {

uint16 nwqid = p9packet.rwalk.nwqid;

uint64 rwalkpacket_size = & P9message_size – 2; // nwqid फ़ील्ड के लिए rwalk हैडर के 2 बाइट्स

Unit_ptr rwalkpacketstart = & P9Client-> P9PacketStart.u.rwalk-> wqids;
uint64 error_code = 0x0C0000186;
uint64 rwalk_message_size = nwqid * 13; // 0xd एक rwalk संरचना का आकार है

अगर (rwalk_message_size <= P9message_size) {

P9Exchange-> Lambda_8972 (int, nwqid, & rwalk_message_size, P9Exchange-> RxContext, & rwalkpacketstart); // लैम्ब्डा_8972, रेवल्क संदेश प्रकार के लिए लैम्बडा_पीटीआर 1 है

} अन्य {

P9Exchange-> P9Client :: SyncContextErrorCallback (error_code, P9Exchange-> RxContext) // SyncContextErrorCallback rwalk संदेश प्रकार के लिए Lambda_PTR2 है

}
}

ProcessReadReply गणना फ़ील्ड का आकार 0x8000 से अधिक नहीं है और इसे P9Exchange-> RxContext के भीतर MDL में लिखता है, एक्सप्लोरर के भीतर फ़ाइल सामग्री देखने के लिए RDBSS स्टैक को वापस पास करने के लिए।

शून्य P9Client :: ProcessReadReply (rmessage_type, * P9Exchange, और P9message_size) {
unint64 count = P9Client-> P9PacketStart.u.rread-> count;
P9Exchange-> Lambda_2275 (गिनती, P9Exchange-> RxContext, & P9message_size);};
लैम्ब्डा_2275 (गणना, P9Exchange-> RxContext, और P9message_icize) {

uint64 अधिकतम = P9Exchange-> RxContext + ऑफसेट; // max_size = 0x8000

unint64 MDL = P9Exchange-> RxContext + ऑफसेट;

अगर (गणना> अधिकतम आकार) समाप्त ();

memmove (& MDL, P9Client-> P9PacketStart.u.rread-> डेटा, गिनती);

}

निष्कर्ष

इस शोध के माध्यम से, हमने P9 प्रोटोकॉल के विंडोज कर्नेल कार्यान्वयन के भीतर एक स्थानीय इनकार सेवा (DoS) की खोज की। जैसा कि समझाया गया है, विंडोज कर्नेल के भीतर कोड निष्पादन हासिल करने के लिए भेद्यता का दोहन नहीं किया जा सकता है ताकि उपयोगकर्ताओं को इस विशिष्ट भेद्यता से कोई जोखिम न हो। दुर्भावनापूर्ण P9 सर्वर हमलों के लिए पूर्व-आवश्यकता के रूप में, एक हमलावर को P9 सर्वर सॉकेट “fsserver” को हाईजैक करना होगा। इसलिए, हम सॉकेट “fsserver” के अपहरण का पता लगाने और रोकने के द्वारा इस हमले को कम कर सकते हैं। McAfee MVISION समापन बिंदु और EDR पी 9 सर्वर सॉकेट “fsserver” अपहरण के खिलाफ कवरेज का पता लगा सकता है और रोक सकता है जिसे आप यहां पढ़ सकते हैं।

हमें उम्मीद है कि यह शोध निम्नलिखित में अंतर्दृष्टि प्रदान करता है:

  1. विंडोज 10 ओएस पर डब्ल्यूएसएल पी 9 प्रोटोकॉल जैसी नई सुविधाओं के लिए भेद्यता शिकार प्रक्रिया
  2. डब्लूएसएल पर एक आभासी लिनक्स फ़ाइल सिस्टम के कार्यान्वयन के कारण जटिलता में बढ़ रही डब्ल्यूएसएल संचार स्टैक को उच्चतर भविष्य के अनुसंधान के लिए समर्थन प्रदान करें
  3. हमारे ग्राहकों के लिए सुरक्षा प्रदान करने के लिए हमारे उत्पाद और नवाचार टीमों के साथ मिलकर काम करने वाले McAfee Advanced Threat Research (ATR) का मूल्य

अंत में, उनके प्रारंभिक विंडोज 10 डब्ल्यूएसएल पी 9 सर्वर अनुसंधान के लिए लिएंड्रो कॉस्टेंटिनो और सेड्रिक कोचीन के लिए एक विशेष धन्यवाद।