Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2024-38063 — CVE-2024-38063 - IPv6 के माध्यम से कर्नेल का दूरस्थ शोषण | Kitploit
उपकरण/GitHubGitHub/faizan-khanx/cve-2024-38063
मेमोरी फोरेंसिकभेद्यता विश्लेषणशोषणरिवर्स इंजीनियरिंगनेटवर्क सुरक्षापेपर और शोधलर्निंग और शिक्षाबाइनरी शोषण
GitHubfaizan-khanx/cve-2024-38063

CVE-2024-38063

CVE-2024-38063 - IPv6 के माध्यम से कर्नेल का दूरस्थ शोषण

रिपॉजिटरी देखें
132 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

CVE-2024-38063 - IPv6 के माध्यम से कर्नेल का दूरस्थ शोषण

  • 13 अगस्त को नवीनतम Windows पैच जारी होने के बाद से मैं tcpip.sys (TCP/IP पैकेट को संभालने वाला कर्नेल ड्राइवर) के विवरण में गहराई से उतरा हुआ हूँ। Windows कर्नेल के सबसे आसानी से पहुँचने योग्य भाग में 9.8 CVSS स्कोर वाली भेद्यता को मैं आसानी से नज़रअंदाज नहीं कर सकता था। मैंने पहले कभी IPv6 (या इसे पार्स करने वाले ड्राइवर) को नहीं देखा था, इसलिए मुझे पता था कि इस भेद्यता को रिवर्स इंजीनियर करने की कोशिश बेहद चुनौतीपूर्ण होगी, लेकिन यह एक अच्छा सीखने का अनुभव होगा।

अब तक का सबसे आसान पैच विश्लेषण

  • आमतौर पर, यह पता लगाने के लिए कि कौन सा कोड परिवर्तन भेद्यता के अनुरूप है, केवल पैच को रिवर्स इंजीनियर करने में भी दिन या सप्ताह लग सकते हैं, लेकिन इस मामले में यह तुरंत हो गया। यह इतना आसान था कि सोशल मीडिया पर कई लोगों ने मुझे बताया कि मैं गलत हूँ और बग कहीं और है। क्या मैंने वास्तव में उनकी बात सुनी और फिर गलत ड्राइवर को रिवर्स करने में पूरा दिन बर्बाद कर दिया? हम शायद कभी नहीं जान पाएंगे।

पूरे ड्राइवर फ़ाइल में केवल एक ही बदलाव किया गया था, जो अंततः वास्तव में बग निकला। image पैच स्थापित करने से पहले और बाद में tcpip.sys का एक bindiff अवलोकन।

पूरे ड्राइवर में केवल एक फ़ंक्शन को संशोधित किया गया है। आमतौर पर, मैं यह पता लगाने में पूरा दिन बिता सकता हूँ कि कौन सा फ़ंक्शन मुझे देखना चाहिए, लेकिन इस बार ऐसा नहीं है। image

Ipv6pProcessOptions() पैच से पहले।

image Ipv6pProcessOptions() . पैच के बाद।

न केवल एक ही फ़ंक्शन बदला गया था, बल्कि कोड की एक ही पंक्ति बदली गई थी।

  • अत्यधिक लंबे नाम वाला Feature_2660322619__private_IsEnabledDeviceUsage_3() फ़ंक्शन कुछ ऐसा है जिसे Microsoft कभी-कभी आंशिक पैच रोलबैक सक्षम करने के लिए जोड़ता है। यह कॉल वैश्विक फ़्लैग या रजिस्ट्री सेटिंग की उपस्थिति की जाँच करता है, जो सेट होने पर फ़ंक्शन को false लौटाने का कारण बनेगा, जिसके परिणामस्वरूप पैच किए गए संस्करण के बजाय मूल कोड निष्पादित किया जाएगा।

  • Microsoft ऐसा इसलिए करता है क्योंकि सुरक्षा पैच कभी-कभी अनजाने में चीजों को तोड़ देते हैं, इसलिए यह सेटिंग एक प्रशासक को पूरे मासिक पैच रोलअप को अनइंस्टॉल किए बिना और अपने सिस्टम सुरक्षा को काफी कमजोर किए बिना एकल भेद्यता को अनपैच करने में सक्षम बनाती है।

  • इसे ध्यान में रखते हुए, यह स्पष्ट है कि यह पैच केवल IppSendErrorList() के कॉल को IppSendError() से बदलता है, जिससे हमें संकेत मिलता है कि समस्या किसी प्रकार की सूची के साथ है। अब तक का सबसे आसान पैच अंतर (या मैंने ऐसा सोचा था)

भेद्यताएँ वैकल्पिक, शोषण अनिवार्य

  • पैच को रिवर्स इंजीनियर करके परिवर्तित कोड ढूँढना चुनौती का केवल आधा हिस्सा है (या इस मामले में 0.1% से भी कम)। शेष प्रक्रिया में कोडबेस को पर्याप्त रूप से रिवर्स इंजीनियर करना शामिल है ताकि यह समझा जा सके कि वास्तव में क्या चल रहा है, यह पता लगाना कि किस प्रकार की भेद्यता को पैच किया गया था, लक्ष्य कोड तक पहुँचने के लिए अनुरोध कैसे तैयार किया जाए, और कौन सी स्थिति शोषण योग्य स्थिति उत्पन्न करती है।

  • पहला भाग काफी आसान है। परिवर्तन Ipv6pProcessOptions() में है, जो हमें बताता है कि यह IPv6 है और इसमें विकल्पों को संसाधित करना शामिल है। तो, RFC पर एक त्वरित नज़र हमें बताती है कि IPv6 विकल्प क्या है और हम इसे कहाँ पा सकते हैं।

image विकिपीडिया से गंतव्य विकल्प हेडर लेआउट।

ठीक है, बढ़िया। हम जो खोज रहे हैं वह गंतव्य विकल्प हेडर प्रतीत होता है, जो मुख्य IPv6 हेडर के ठीक बाद आता है। आइए एक परीक्षण IPv6 पैकेट तैयार करने के लिए Python लाइब्रेरी 'scapy' का उपयोग करें।

नोट: स्पूफ़ किए गए IP पतों का उपयोग करके DDoS हमलों को कम करने के लिए, Windows कच्चे IP पैकेट बनाने की क्षमता को प्रतिबंधित करता है। इस कारण से, मैंने अपने प्रूफ-ऑफ-कॉन्सेप्ट को विकसित करने के लिए Linux का उपयोग करने का विकल्प चुना। जबकि Linux उपयोगकर्ताओं को कच्चे लेयर 2 और लेयर 3 पैकेट बनाने और भेजने की अनुमति देता है, इसके लिए Python स्क्रिप्ट को रूट के रूप में चलाना आवश्यक है।

root@kitploit:~
import sys
import struct
from scapy.all import *


def send_ipv6_option_packet(dest_ip):
	ethernet_header = Ether()
	ip_header = IPv6(dst=dest_ip)
	options_header = IPv6ExtHdrDestOpt()
	sendp(ethernet_header / ip_header / options_header)
	
	
if len(sys.argv) < 2:
	print('Use: python3 script.py <target_ipv6_address>')
	exit(-1)

send_ipv6_option_packet(sys.argv[1])
  • tcpip!Ipv6pProcessOptions पर ब्रेकपॉइंट सेट करने के बाद, फिर स्क्रिप्ट चलाने पर, यह स्पष्ट हो गया कि भेद्य फ़ंक्शन तक पहुँचने के लिए केवल एक खाली विकल्प संरचना के साथ एक IPv6 पैकेट भेजना आवश्यक था। फिर मैंने यह देखने के लिए संरचना में कुछ अमान्य विकल्प जोड़ने का प्रयास किया कि क्या मैं IppSendErrorList() के कॉल तक पहुँच सकता हूँ।

एक संक्षिप्त कोड समीक्षा ने संकेत दिया कि लगभग कोई भी अमान्य विकल्प स्वरूपण IppSendErrorList के कॉल को ट्रिगर कर सकता है। इसलिए, मैंने एक अमान्य लंबाई (65535 बाइट्स से कम) के साथ जंबो पैकेट विकल्प का उपयोग करने का निर्णय लिया।

options_header = IPv6ExtHdrDestOpt(options=[Jumbo(jumboplen=0x1337)])

  • तो, IppSendErrorList() वास्तव में क्या करता है? खैर, कोड काफी सरल है। image संपूर्ण IppSendErrorList फ़ंक्शन।

  • कोड एक लिंक्ड सूची को पुनरावृत्त करता है और सूची में प्रत्येक आइटम पर IppSendError() को कॉल करता है। फिर से, सितारे संरेखित हो गए हैं और अब तक चीजें आसान रही हैं। यदि IppSendErrorList सूची में प्रत्येक आइटम के लिए IppSendError को कॉल करता है, और पैच IppSendErrorList के कॉल को IppSendError से बदल देता है, तो समस्या तब होती है जब IppSendError को पहले आइटम के अलावा किसी अन्य सूची आइटम पर कॉल किया जाता है।

वह एक सूची बना रहा है, वह इसे 52,567 बार जाँच रहा है

  • यह वह जगह है जहाँ चीजें स्पष्ट से असामान्य रूप से कठिन हो गईं, हालाँकि मुझे लगता है कि इसका एक बड़ा हिस्सा मेरे दो उपलब्ध मस्तिष्क कोशिकाओं में से एक के खराब कोविड संक्रमण से लड़ने में व्यस्त होने के कारण था। मैंने कोड के कुछ हिस्सों को समझने, सो जाने, फिर यह भूल जाने में कुछ दिन खो दिए कि मैंने क्या पता लगाया था। पूरी प्रक्रिया में यह पता लगाने के लिए tcpip.sys के कुछ हिस्सों को रिवर्स इंजीनियर करने में एक सप्ताह से अधिक का समय लगा कि क्या चल रहा था। लेकिन Axel का ब्लॉग पोस्ट बेहद मददगार था।

  • Axel द्वारा रिवर्स इंजीनियर किए गए फ़ंक्शन और संरचना को देखकर, और वे किन अन्य फ़ंक्शनों को पास किए जाते हैं, यह स्पष्ट है कि Ipv6pProcessOptions() में पारित एकमात्र तर्क लेख में परिभाषित वही packet_t संरचना है। अनिवार्य रूप से, Ipv6pProcessOptions को पारित किया गया पॉइंटर, और IppSendErrorList द्वारा पुनरावृत्त किया गया, पैकेटों की एक लिंक्ड-सूची है।

  • इसलिए, मैंने Ipv6pProcessOptions() पर एक ब्रेकपॉइंट सेट किया और सूची का निरीक्षण किया।

image

सूची->अगली प्रविष्टि NULL है।

  • हर बार जब मेरा ब्रेकपॉइंट हिट हुआ, सूची में केवल एक पैकेट था। मैंने यह पता लगाने में जितना स्वीकार करना चाहूँगा उससे कहीं अधिक समय बिताया कि क्यों और कैसे मेरी सूची को वास्तव में एक सूची बनाया जाए। मेरा पहला विचार IPv6 विखंडन था: IPv6 प्रेषकों को बड़े पैकेटों को अलग-अलग छोटे पैकेटों में विभाजित करने की अनुमति देता है, जिसे एक सूची में एक साथ रखना समझ में आता है।

  • व्यापक रिवर्स इंजीनियरिंग के बाद, मैंने पुष्टि की कि मेरी धारणाएँ सही थीं, हालाँकि खंड सूची उस सूची से संबंधित नहीं है जिसके साथ हम यहाँ काम कर रहे हैं।

  • मैं वास्तव में पूरी तरह से संयोग से उत्तर ढूँढने में समाप्त हुआ। कभी-कभी, सूची भर जाती थी, लेकिन कारण स्पष्ट नहीं था। बहुत चक्कर लगाने के बाद, मुझे एहसास हुआ कि जब मेरा कर्नेल ब्रेकपॉइंट ट्रिगर होता है, तो यह पूरे कर्नेल को रोक देता है, जिससे नेटवर्क एडॉप्टर पैकेट जमा करता है। जब कर्नेल फिर से शुरू होता है, तो ये पैकेट एक अच्छी साफ सूची में स्टैक के नीचे tcpip.sys को भेज दिए जाते हैं। यह केवल तब हुआ जब पैकेट कर्नेल के रुकने के दौरान भेजे गए थे, लेकिन अगले ब्रेकपॉइंट के हिट होने से पहले संसाधित नहीं हुए थे।

  • यह व्यवहार संभवतः एक प्रदर्शन अनुकूलन है, जहाँ कम थ्रूपुट पर, कर्नेल पैकेटों को व्यक्तिगत रूप से संसाधित करता है, लेकिन उच्च मात्रा में, पैकेटों को सूचियों में व्यवस्थित किया जाता है और बैचों में संसाधित किया जाता है। सबसे अधिक संभावना है कि प्रसंस्करण को गति देने के लिए सूचियों को प्रोटोकॉल और स्रोत पते जैसे कारकों के आधार पर अलग किया जाता है, इसलिए हमारी सूची में केवल हमारे द्वारा भेजे गए IPv6 पैकेट होने चाहिए।

  • अब जब हम जानते हैं कि उच्च थ्रूपुट के दौरान पैकेट सूचियों में संयोजित हो जाते हैं, तो यह स्पष्ट है कि सबसे आसान विकल्प क्या होगा। हमारा DoS PoC विडंबनापूर्ण रूप से DoS स्थिति को ट्रिगर करने के लिए DoS का उपयोग करने वाला है। यदि हम सिस्टम को IPv6 पैकेटों के विस्फोटों से भर देते हैं, तो हमें IppSendErrorList() को एक अच्छी बड़ी सूची भेजने में सक्षम होना चाहिए।

  • पहले तो, मैंने कितने भी पैकेट भेजे, फिर भी मैं केवल कर्नेल को रोकने पर ही सूची को n > 1 पा सका। लेकिन... चूँकि हम Python (दर्दनाक रूप से धीमी) का उपयोग कर रहे हैं, एक VM में (दोगुनी दर्दनाक रूप से धीमी), हमें शायद कुछ सेटिंग्स बदलने की आवश्यकता होगी। अपने हमला सिस्टम पर हो रहे VM-सेप्शन का मुकाबला करने के लिए, मैंने लक्ष्य VM को केवल एकल CPU कोर का उपयोग करने के लिए पुन: कॉन्फ़िगर करने का निर्णय लिया।

image

बढ़िया! पैकेट सूची अब बहुत सारी प्रविष्टियों वाली एक सूची है!

  • तो, पता चला कि VM के अंदर VM DoS के लिए सबसे अच्छा विकल्प नहीं है, किसने सोचा होगा? लेकिन हमने इसे अंततः काम कर लिया। अब, हमें बस यह पता लगाने की आवश्यकता है कि IppSendError() क्या करता है और समस्या किस भाग में है।

फिर से हमेशा के लिए और अधिक रिवर्सिंग।

  • कुछ व्यापक रिवर्स इंजीनियरिंग के बाद, यह बहुत स्पष्ट हो गया कि IppSendError क्या करता है। सामान्य परिस्थितियों में, यह net_buffer_list->Status को 0xC000021B (STATUS_DATA_NOT_ACCEPTED) पर सेट करके पैकेट को अक्षम कर देता है। फिर, यह त्रुटिपूर्ण पैकेट के बारे में जानकारी वाली एक ICMP त्रुटि प्रेषक को वापस भेजता है।

    image IppSendError के दो प्रासंगिक भाग।

  • मेरा पहला कदम यह देखना था कि क्या tcpip.sys में कोई ऐसे फ़ंक्शन हैं जो net_buffer_list->Status मान को अनदेखा करते हैं। इसके परिणामस्वरूप ड्राइवर उन पैकेटों को संसाधित करेगा जो अपरिभाषित या अप्रत्याशित स्थितियों में हैं, उम्मीद है कि एक शोषण की स्थिति पैदा होगी।

image

पैकेटों को संसाधित करने के लिए जिम्मेदार मुख्य लूप।

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

  • बहुत अधिक रिवर्स इंजीनियरिंग के बाद, मुझे IppSendError के बिल्कुल नीचे निम्नलिखित कोड मिला।

image

IppSendError में एक कोड पथ जो packet_size को शून्य पर सेट करता है।

  • जब IppSendErrorList, और इस प्रकार IppSendError, को तर्क always_send_icmp के true पर सेट करके कॉल किया जाता है, तो ऐसा प्रतीत होता है कि यह सूची में प्रत्येक पैकेट को ICMP त्रुटि भेजने का प्रयास करता है।

  • फिर, शायद केवल ईश्वर को ज्ञात कारणों से, यह कोड के एक ब्लॉक तक पहुँचता है जहाँ packet->packet_size फ़ील्ड शून्य पर सेट हो जाता है।

  • always_send_icmp को true पर सेट करने के लिए, हमें बस 'Option Type' मान को 0x80 से बड़ी किसी भी संख्या पर सेट करके विकल्प हेडर प्रसंस्करण में एक विशिष्ट त्रुटि उत्पन्न करनी होगी।

root@kitploit:~
def build_malicious_option(next_header, header_length, option_type, option_length):
    dest_options_header = 60
	
    options_header = struct.pack('BBBB', next_header, header_length, option_type, option_length) + b'1337'
    return Ether(dst=mac_addr) / IPv6(dst=ip_addr, nh=dest_options_header) / raw(options_header)

packet = build_malicious_option(next_header=59, header_length=0, option_type=0x81, option_length=0)	
sendp(packet)

लेकिन, क्या packet_size को शून्य पर सेट करने से पार्सर टूट नहीं जाना चाहिए?

image

पैकेटों को संसाधित करने के लिए जिम्मेदार मुख्य लूप का एक अंश।

  • पैकेट हैंडलर बस packet->next_header मान के आधार पर एक VTable फ़ंक्शन को कॉल करता है, जो प्री-पार्सिंग के दौरान सेट होने के बाद से अपरिवर्तित रहता है। यह पैकेट प्रसंस्करण को जारी रखने की अनुमति देता है और हमें यह भी नियंत्रण देता है कि कौन सा प्रसंस्करण होता है।

  • क्योंकि packet->next_header मान IPv6 पैकेट के 'Next Header' फ़ील्ड से प्राप्त होता है, हम इसे किसी भी मान्य IPv6 हेडर मान पर सेट कर सकते हैं, और लूप संबंधित पार्सर को कॉल करेगा। यह हमें हमले की बहुत सारी संभावित सतह देता है। image

    IPv6 पैकेट प्रारूप।

  • बस इतना करना बाकी है कि IPv6 पार्सर का एक सुलभ भाग खोजें जो packet_size फ़ील्ड के साथ कुछ मूर्खतापूर्ण करता हो।

वापस विखंडन की ओर

  • पहली जगह जहाँ मैंने देखने का फैसला किया, वह IPv6 खंड पार्सर था, क्योंकि वहाँ पुरानी cve-2021-24086 भेद्यता थी, इसलिए यह और अधिक विचित्र कोड खोजने के लिए एक अच्छी जगह लग रही थी। image

एह... यह बहुत करीब है, लेकिन बहुत दूर भी है

  • हमारे पास यहाँ एक भेद्यता है, लेकिन यह RCE नहीं है।

  • अनिवार्य रूप से, अधिकांश CPU पर, रजिस्टर चक्रीय होते हैं। यदि आप किसी रजिस्टर को उसके अधिकतम संभावित मान से अधिक बढ़ाते हैं, तो यह वापस शून्य पर आ जाता है। इसी प्रकार, यदि आप इसे इसके न्यूनतम संभावित मान से कम करते हैं, तो यह उच्चतम संभावित मान पर आ जाता है। इन्हें क्रमशः पूर्णांक अतिप्रवाह और पूर्णांक अंतर्प्रवाह कहा जाता है। यह व्यवहार हस्ताक्षरित पूर्णांकों के लिए थोड़ा अलग है, लेकिन हम यहाँ उनसे नहीं निपट रहे हैं।

  • पहली पंक्ति, fragment_size = LOWORD(packet->packet_size) - 0x30, में निम्नलिखित ASM कोड शामिल है:

    image

    खंड आकार की गणना करने वाला ASM कोड।

  • AX, EAX रजिस्टर के निचले 16 बिट हैं। हालाँकि EAX रजिस्टर 32-बिट है, AX ऐसे काम करता है जैसे कि यह अपना स्वयं का 16-बिट रजिस्टर हो, इसलिए कोई भी अतिप्रवाह या अंतर्प्रवाह AX तक ही सीमित रहता है, और EAX रजिस्टर के शेष भाग को प्रभावित नहीं करेगा। यह अविश्वसनीय रूप से सुविधाजनक है क्योंकि EAX रजिस्टर पर एक अंतर्प्रवाह के परिणामस्वरूप 4 बिलियन का मान होगा, जिसके परिणामस्वरूप 4GB मेमोरी आवंटित करने का प्रयास होगा, जो संभवतः विफल हो जाएगा।

  • चूँकि packet->packet_size का मान शून्य है, यह कोड ax को शून्य पर सेट करता है, फिर उसमें से 0x30 घटाता है।

  • सामान्य परिस्थितियों में पैकेट हेडर 0x30 बाइट्स होता है, इसलिए packet_size - 0x30 खंड डेटा का आकार है।

  • हमारे मामले में, packet->packet_size 0 है, इसलिए इसमें से 1 घटाने पर भी रजिस्टर अधिकतम संभव 16-बिट पूर्णांक मान (0xFFFF) पर घूम जाएगा। चूँकि हम 0x30 घटा रहे हैं, AX का मान अंतर्प्रवाहित हो जाएगा और MAX_VALUE - 0x2F, या 0xFFD0 हो जाएगा, जो 65,488 है।

  • दुर्भाग्य से, चूँकि मेमोरी आवंटन और डेटा कॉपी करने दोनों के लिए समान गणना का उपयोग किया जाता है, हमें बफर अतिप्रवाह नहीं मिलता है। मेरा मानना है कि RtlCopyMdlToBuffer() स्रोत बफर पर भी सीमा जाँच करता है, इसलिए हमें आउट-ऑफ-बाउंड्स रीड भी नहीं मिलता है। हालाँकि, हम पूरी तरह से खाली हाथ नहीं जाते हैं।

IPv6 खंड मेमोरी में तब तक बने रहेंगे जब तक तीन स्थितियों में से एक न हो:

  • हम अपने विखंडन को इतना बुरी तरह से गड़बड़ कर देते हैं कि सिस्टम हमें रुकने का समय बताता है।
  • हम एक खंड भेजते हैं जिसमें 'More' फ़ील्ड 0 पर सेट है, जो इंगित करता है कि यह अंतिम खंड है, और सिस्टम पुन: संयोजन शुरू कर देगा।
  • हम टाइमआउट अवधि (60 सेकंड) समाप्त होने से पहले अंतिम खंड नहीं भेजते हैं, और सिस्टम खंडों को छोड़ देता है।
  • Ipv6pReassemblyTimeout() को स्थिति 3 के तहत बुलाया जाता है, तो आइए देखें कि इसका शोषण कैसे किया जा सकता है।

Ipv6pReassemblyTimeout() को स्थिति 3 के तहत बुलाया जाता है, तो आइए देखें कि इसका शोषण कैसे किया जा सकता है।

image

यह वही है जो हमें चाहिए!

  • पहले, हमारी समस्या यह थी कि कोड मेमोरी आवंटन और कॉपी ऑपरेशन दोनों के लिए बिल्कुल समान गणना का उपयोग करता था। दूसरी ओर, यह कोड ऐसा नहीं करता है। आइए ASM पर गहराई से नज़र डालें कि यह कैसे शोषण योग्य है

image

आवंटन आकार की गणना के लिए जिम्मेदार असेंबली कोड।

  • जैसा कि आप यहाँ देख सकते हैं, गणना का पहला भाग (fragment_list->net_buffer_length + reassembly->packet_length + 8) 16-बिट DX रजिस्टर का उपयोग करके किया जाता है।

  • यदि आपको पहले से याद होगा, हमने reassembly->packet_length को 0xFFD0 होने के लिए अंतर्प्रवाहित किया था। तो DX रजिस्टर, 8 बाइट्स जोड़ने के बाद, 0xFFD8 है। यदि fragment_list->net_buffer_length 0x27 (39 बाइट्स) से बड़ा है, तो DX अतिप्रवाहित हो जाएगा और शून्य पर रीसेट हो जाएगा।

  • fragment_list->net_buffer_length लगभग 0x38 बाइट्स होना चाहिए, इसलिए इसका परिणाम DX रजिस्टर को 8 पर अतिप्रवाहित करने में होगा। 0x28 बाइट्स जोड़े जाने के बाद, हमें केवल 48 बाइट्स का मेमोरी आवंटन मिलेगा।

  • चूँकि बाद के memmove() कॉल आकार के लिए केवल अपरिवर्तित reassembly->packet_length मान का उपयोग करते हैं, इसके परिणामस्वरूप 65,488 बाइट्स reassembly->payload से 30 बाइट बफर में कॉपी हो जाएंगे। - एक बड़ा अतिरिक्त बोनस यह है कि कॉपी किया गया अधिकांश डेटा खंड पेलोड से आता है, जिसे हम नियंत्रित करते हैं, और किसी भी प्रारूप का मनमाना डेटा हो सकता है, इसलिए हमें एक अच्छा, काफी नियंत्रणीय कर्नेल पूल-आधारित बफर अतिप्रवाह मिलता है।

  • भेद्यता को ट्रिगर करने का मौका पाने के लिए, हमें IppSendErrorList को कॉल करने के समय लिंक्ड सूची में विकृत विकल्प पैकेट के बाद एक या अधिक खंड पैकेट रखने की आवश्यकता है। हालाँकि, मेरे परीक्षण से, यह शोषण की गारंटी नहीं देता है। मेरा मानना है कि कुछ अन्य शर्तें भी हैं जिन्हें पूरा करने की आवश्यकता है। मुझे संदेह है, लेकिन पुष्टि नहीं हुई है, कि IppSendError में सिंक्रनाइज़ेशन कोड का अर्थ है कि हमें एक दौड़ की स्थिति भी जीतनी होगी।

सोशल मीडिया

Faizan's GitHub stats

instagram twitter linkedin github

टूल डाउनलोड करें
  • क्योंकि ExAllocatePoolWithTagPriority() आवंटित मेमोरी को शून्य नहीं करता है, और RtlCopyMdlToBuffer() केवल उपलब्ध डेटा की वास्तविक मात्रा को कॉपी करता है, हमें लगभग 65kb की अनइनिशियलाइज़्ड कर्नेल मेमोरी मिलती है। चूँकि मेमोरी पते डीलोकेशन के बाद पुनर्चक्रित हो जाते हैं, बफर संभवतः उस चीज़ से भरा होगा जो पुन: आवंटन से पहले पते पर संग्रहीत थी। यदि हम विखंडन का उपयोग करके एक पैकेट बना सकते हैं जो हमें वापस भेजा जाता है, जैसे ICMP Echo अनुरोध, तो हम संभावित रूप से यादृच्छिक कर्नेल मेमोरी लीक कर सकते हैं, जिससे ASLR बायपास हो सकता है।

  • इसके अलावा, कोड reassembly->fragment_size को अंतर्प्रवाहित 16-बिट पूर्णांक (65,488) पर भी सेट करता है, इसलिए अब हमारे पास दो अलग-अलग चर हैं जिनका उपयोग हम संभावित रूप से बफर अतिप्रवाह पैदा करने के लिए कर सकते हैं।

  • समाधान (या कम से कम उनमें से एक) Ipv6pReassemblyTimeout() है। जबकि हम प्रारंभिक खंड हैंडलिंग में अतिप्रवाह नहीं पैदा कर सकते, हम स्पष्ट रूप से सफाई के दौरान ऐसा कर सकते हैं।