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

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

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

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

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

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2022-37969 — CVE-2022-37969 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, एक Windows कॉमन लॉग फ़ाइल सिस्टम ड्राइवर स्थानीय विशेषाधिकार वृद्धि। यह हीप स्प्रे, टोकन स्टीलिंग और आर्बिट्ररी कर्नेल राइट का प्रदर्शन करके SYSTEM विशेषाधिकार प्राप्त करता है। | Kitploit
उपकरण/GitHubGitHub/fortra/cve-2022-37969
विशेषाधिकार वृद्धिमेमोरी फोरेंसिकभेद्यता विश्लेषणशोषणबाइनरी शोषण
GitHubfortra/cve-2022-37969

CVE-2022-37969

CVE-2022-37969 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, एक Windows कॉमन लॉग फ़ाइल सिस्टम ड्राइवर स्थानीय विशेषाधिकार वृद्धि। यह हीप स्प्रे, टोकन स्टीलिंग और आर्बिट्ररी कर्नेल राइट का प्रदर्शन करके SYSTEM विशेषाधिकार प्राप्त करता है।

रिपॉजिटरी देखें
1353813 साल पहलेKitploit द्वारा समीक्षित

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

सभी देखें →

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

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

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

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

CVE-2022-37969 Windows स्थानीय विशेषाधिकार वृद्धि (Local Privilege Escalation) PoC

authors: Ricardo Narvaja & Daniel Kazimirow (Solid)

केवल प्रदर्शन उद्देश्यों के लिए। पूर्ण एक्सप्लॉइट कमजोर Windows 11 21H2 सिस्टम पर काम करता है।

पहले Zscaler द्वारा प्रकाशित जानकारी पर आधारित कार्यात्मक PoC

व्याख्या लेख देखें Understanding the CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation।

उपयोग (Usage)

Understanding the CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation.

एक्सप्लॉइटेशन वॉकथ्रू:

  • प्रारंभिक BLF लॉग फ़ाइल बनाना
    • कई रैंडम BLF लॉग फ़ाइलें बनाना
    • प्रारंभिक लॉग फ़ाइल तैयार करना
    • नियंत्रित Heap Spray करना
    • CreatePipe() / NtFsControlFile() विधियाँ तैयार करना
    • मेमोरी तैयार होने के बाद कमजोरी को ट्रिगर करना
    • System Token पढ़ना
    • टोकन को मान्य करना
    • अपनी प्रक्रिया के टोकन को सिस्टम टोकन से बदलना
    • प्रक्रिया को system के रूप में निष्पादित करना
    • पैच को रिवर्स करना: संरचनाओं का विश्लेषण
    • "pContainer" पॉइंटर को दूषित करना
    • पैच की पुन: समीक्षा
    • SignatureOffset को दूषित करना
    • अधिक मानों को दूषित करना
    • SYSTEM token पढ़ने की अनुमति देने वाले फ़ंक्शनों को नियंत्रित करना
    • स्थानीय विशेषाधिकार वृद्धि प्राप्त करने के लिए अपनी प्रक्रिया लिखना
    • PoC सोर्स कोड

यहाँ उपयोग किया गया परिदृश्य Windows 11 21H2 (OS Build 22000.918) clfs.sys v10.0.22000.918 था

प्रारंभिक BLF लॉग फ़ाइल बनाना

पहला चरण MyLog.blf नामक एक फ़ाइल को पब्लिक फ़ोल्डर (%public%) में बनाना है, CreateLogFile() फ़ंक्शन का उपयोग करके:

कई रैंडम BLF लॉग फ़ाइलें बनाना

फिर यह एक Loop का उपयोग करके रैंडम नामों के साथ कई लॉग फ़ाइलें बनाता है।

और लूप के भीतर, यह हमारे getBigPoolInfo() फ़ंक्शन को कॉल करता है:

यह NtQuerySystemInformation() को कॉल करता है, पहले तर्क के रूप में 0x42 (66 दशमलव) के साथ, यह v5 में बिगपूल में किए गए raids के बारे में जानकारी लौटाएगा, जिसकी संरचना SYSTEM_BIGPOOL_INFORMATION प्रकार की होती है।

हमें इस फ़ंक्शन को दो बार कॉल करना होता है। पहली बार यह एक त्रुटि लौटाएगा, लेकिन यह हमें दूसरी बार कॉल करने के लिए बफर का सही आकार देगा ताकि वांछित जानकारी प्राप्त हो सके।

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

v5 को SYSTEM_BIG_POOL_INFORMATION संरचना की जानकारी प्राप्त होगी।

बिगपूल में आवंटनों की संख्या, Count नामक पहले फ़ील्ड में संग्रहीत होती है, दूसरे फ़ील्ड में SYSTEM_BIGPOOL_ENTRY संरचनाओं की एक सरणी होती है।

फिर हम सभी संरचनाओं में "Clfs" टैग और आकार 0x7a00 के लिए खोज करेंगे।

यह kernelAddrArray नामक एक सरणी में VirtualAddress संग्रहीत करता है जो प्रत्येक संरचना का पहला फ़ील्ड है जिसमें CLFS टैग और आकार 0x7a00 होता है। अब से, जो पूल दोनों शर्तों को पूरा करते हैं उन्हें "right pools" कहा जाएगा।

प्रत्येक right pool को सरणी में संग्रहीत करने के अलावा, यह अंतिम पाए गए right pool को a2 चर की सामग्री में संग्रहीत करता है, जिसका उपयोग फ़ंक्शन के तर्क के रूप में किया जाता है।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

इस प्रकार a2 हमेशा CLFS टैग और आकार 0x7a00 वाले अंतिम बनाए गए right pool की ओर इंगित करता है।

चर v26 हमेशा पिछला पाया गया right pool संग्रहीत करता है क्योंकि getBigPoolinfo() को कॉल करने से पहले यह v24 के बराबर होता है (v26=v24), लेकिन इस कॉल से बाहर निकलते समय v24 को अंतिम पाए गए right pool के साथ अद्यतन किया जाता है, और v26 पिछले पाए गए right pool के साथ रहता है।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

फिर यह दोनों पतों को घटाता है, और यदि परिणाम नकारात्मक है, तो संकार्यों को उलट देता है ताकि यह हमेशा सकारात्मक रहे।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

इस प्रकार v32 में अंतिम दो पाए गए right pool के VirtualAddress के बीच का अंतर संग्रहीत होगा।

फिर यह कुछ ऐसा ही करता है, इस मामले में v23 शुरू में शून्य होता है इसलिए पहली बार v23=v32 होता है।

अगली बार लूप में v23 का मान अभी भी समान होता है और शून्य नहीं होता, इसलिए यह टूट जाता है और यहाँ आता है।

V32 में अंतिम अंतर होता है और v23 में पिछला अंतर होता है, यदि वे बराबर हैं, तो यह बाहर आता है और एक बढ़ाता है, लेकिन काउंटर को शून्य पर रीसेट कर देता है।

विचार यह है कि CLFS टैग और आकार 0x7a00 के 6 लगातार तुलनाओं को खोजा जाए जिनके अंतर समान हों, और वह अंतर 0x11000 होगा। निष्पादित करते समय हम देखेंगे कि जब यह 6 (क्योंकि यह शुरू से शुरू होता है) समान दूरियों वाले लगातार पाता है तो यह उनके बीच का अंतर मान देगा।

Texto Descripción generada automáticamente

वहाँ हम देखते हैं कि उसे 6 लगातार मिले और वह लॉग फ़ाइलें बनाने के लूप से बाहर निकल गया।

"public" फ़ोल्डर में हम बनाई गई फ़ाइलें देख सकते हैं

प्रारंभिक लॉग फ़ाइल तैयार करना:

हमारा craftFile() फ़ंक्शन मूल फ़ाइल (MyLog.blf) खोलता है और बग को ट्रिगर करने के लिए उसे संशोधित करता है।

फ़ाइल को संशोधित करने के बाद, CRC32 बदलना आवश्यक है, अन्यथा हमें एक दूषित फ़ाइल त्रुटि मिलेगी

यह मान फ़ाइल के ऑफसेट 0x80C पर स्थित है।

नियंत्रित Heap Spray करना

इसके बाद, यह एक HeapSpray करता है, मेमोरी आवंटित करने के लिए VirtualAlloc() फ़ंक्शन का उपयोग करते हुए, क्रमशः मनमाने पतों 0x10000 और 0x5000000 पर, और दूसरे आवंटन (0x10000) में मान 0x5000000 को हर 0x10 बाइट्स पर सहेजता है।

CreatePipe() / NtFsControlFile() विधियाँ तैयार करना

यह एक अनाम पाइप बनाने के लिए CreatePipe() का उपयोग करता है और एक विशेषता जोड़ने के लिए तर्क के रूप में 0x11003c का उपयोग करके NtFsControlFile() को कॉल करता है, बाद में आप इसे पढ़ने के लिए 0x110038 तर्क के साथ इसी फ़ंक्शन को कॉल कर सकते हैं।

इस विधि के अधिक विवरण यहाँ पाए जा सकते हैं

वहाँ हम इनपुट बफर देखते हैं जो वह विशेषता है जिसे हम जोड़ रहे हैं, यदि हम तर्क 0x11038 के साथ NtFsControlFile() को फिर से कॉल करते हैं तो आउटपुट में यह वही विशेषता लौटानी चाहिए।

बनाई गई विशेषता के टैग (NpAt) के लिए पूल खोजें

और जब यह इसे पाता है, तो यह इस पूल के VirtualAddress को v30.Pointer में सहेजता है।

V30.pointer+24 कर्नेल पूल में AttributeValueSize की ओर इंगित करता है और इसे उन HeapSprays में से एक में सहेजता है जो हमने पहले बनाए थे।

विचार यह है कि उस कर्नेल पते+8 पर लिखा जाए, ताकि AttributeValue को अधिलेखित किया जा सके।

Texto Descripción generada automáticamente

PipeAttribute संरचना के पहले फ़ील्ड के रूप में एक LIST_ENTRY होता है जिसका आकार 16 बाइट्स होता है, फिर विशेषता के नाम की ओर एक पॉइंटर होता है जिसका आकार 8 बाइट्स होता है और फिर 0x18 (24 दशमलव) पर AttributeValueSize फ़ील्ड आता है जिसे हम HeapSpray में संग्रहीत कर रहे हैं।

उसके बाद, हम usermode में CLFS.sys और ntoskrnl लोड करते हैं, और GetProcAddress() का उपयोग करके ClfsEarlierLsn() और SeSetAccessStateGenericMapping() फ़ंक्शनों के पते ढूंढते हैं।

फिर हम FindKernelModulesBase() फ़ंक्शन को कॉल करते हैं जो NtquerySystemInformation() का उपयोग करके दोनों समान मॉड्यूल का कर्नेल आधार ढूंढेगा, इस बार SystemModuleInformation तर्क के साथ ताकि सभी मॉड्यूल के बारे में जानकारी लौटाई जा सके।

इस प्रकार, हम प्रत्येक फ़ंक्शन के ऑफसेट की गणना कर सकते हैं, और फिर उन्हें कर्नेल में प्राप्त कर सकते हैं

मेमोरी तैयार होने के बाद कमजोरी ट्रिगर होगी:

pipeArbitraryWrite() फ़ंक्शन को दो बार कॉल किया जाता है, एक फ्लैग होता है जो पहली कॉल के लिए शुरू में शून्य होता है और जब दूसरी कॉल में इसका मान 1 होता है, तो यह HeapSpray के मानों को बदल देगा।

Texto Descripción generada automáticamente

पहली कॉल में 0x5000000 मेमोरी पते पर निम्नलिखित मान स्थित होते हैं

याद रखें कि यह मान उस दिशा में आवंटित होने के अलावा, हमारे HeapSpray में संग्रहीत होता है।

पहली कॉल के बाद मेमोरी इस प्रकार होती है, जैसा कि हमने कहा, लगभग 0x5000000 के पते पर

और मेमोरी 0x10000 से HeapSpray में यह हर 0x10 बाइट्स पर AttributeValueSize का पॉइंटर संग्रहीत करेगा, साथ ही 0x5000000 का पॉइंटर भी।

System Token पढ़ना:

यह अनुक्रम बग को ट्रिगर करेगा:

तैयार की गई फ़ाइल पर और एक अन्य रैंडम नाम वाली फ़ाइल पर CreateLogFile() फिर से कॉल किया जाता है।

फिर उन फ़ाइलों के हैंडल का उपयोग करके AddLogContainer() कॉल किया जाता है।

NtSetinformationFile() कॉल किया जाता है, और हैंडल बंद कर दिए जाते हैं जिससे पॉइंटर दूषित हो जाता है (इसे बाद में समझाया जाएगा)

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente con confianza media

HeapSpray, इस बिंदु पर BSOD होने से रोकता है:

वहाँ एक ब्रेकपॉइंट सेट करके, हम देख सकते हैं कि पॉइंटर दूषित है और हमारे HeapSpray की ओर इंगित करता है, जिससे हम vtable के अगले दो फ़ंक्शन कॉलों को संभाल सकते हैं।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Texto Descripción generada automáticamente

RAX मान 0x5000000 लेता है और पहले 0x5000000+18 पर स्थित फ़ंक्शन पर जाता है और फिर 0x5000000+8 पर।

Texto Descripción generada automáticamente con confianza media

Imagen que contiene Interfaz de usuario gráfica Descripción generada automáticamente

तो पहले fnClfsEarlierLsn() पर कूदें और फिर fnSeSetAccessStateGenericMapping() पर।

हम ब्रेकपॉइंट से ट्रेस करते हैं और देखते हैं कि यह CLFS!ClfsEarlierLsn() तक पहुँचता है।

Texto Descripción generada automáticamente

यह फ़ंक्शन विशेष रूप से इसलिए कॉल किया जाता है क्योंकि जब यह लौटता है, तो यह EDX को 0xFFFFFFFF पर सेट करता है

Interfaz de usuario gráfica Descripción generada automáticamente con confianza media

पते 0xFFFFFFFF पर हमने SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF000 का परिणाम संग्रहीत किया था

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

जैसा कि हमने उल्लेख किया, CLFS!ClfsEarlierLsn() से लौटते समय, RDX का मान 0x00000000FFFFFFFF होता है

Texto Descripción generada automáticamente

हम दूसरे फ़ंक्शन nt!SeSetAccessStateGenericMapping() पर आते हैं

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

यह फ़ंक्शन उपयोगी है, क्योंकि RCX हमारे HeapSpray की ओर इंगित करता है, और RDX का मान 0xFFFFFFFF है, जिसकी सामग्री हम नियंत्रित करते हैं

Interfaz de usuario gráfica, Aplicación, Teams Descripción generada automáticamente

Texto Descripción generada automáticamente

RCX+0x48 की सामग्री में AttributeValueSize का पॉइंटर होता है जिसे v30.Pointer+24 में संग्रहीत किया गया था

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Texto Descripción generada automáticamente con confianza media

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

AttributeValueSize का वह पॉइंटर मान RAX में ले जाया जाता है, फिर पते 0xFFFFFFFF की सामग्री पढ़ी जाती है जहाँ हमने SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF000 का पता संग्रहीत किया था।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

फिर RAX+8 पर अगले फ़ील्ड को अधिलेखित करता है जो AttributeValue() है

Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

बेशक, AttributeValue सामान्य रूप से कर्नेल में उस विशेषता की ओर इंगित करेगा जिसे हमने जोड़ा था।

Calendario Descripción generada automáticamente

और अब हम इसे system _EPROCESS & 0xFFFFFFFFFFFFFFF00 के परिणाम के पॉइंटर के साथ अधिलेखित करेंगे।

इसका मतलब होगा कि जब हम NtFsControlFile() फ़ंक्शन को फिर से कॉल करते हैं, इस बार विशेषता पढ़ने के लिए 0x110038 तर्क के साथ, तो उन "A" को लौटाने के बजाय जो AttributeValue पॉइंटर द्वारा इंगित किए गए थे, यह अब _EPRROCESS & 0xFFFFFFFFFFFFFFFFF000 से अनुरोधित बाइट्स की संख्या पढ़ेगा और उन्हें आउटपुट बफर में लौटाएगा, जिससे हम पहली कॉल में SYSTEM TOKEN का मान प्राप्त कर सकते हैं।

Texto Descripción generada automáticamente

v9b Output Buffer का प्रारंभिक पता है जहाँ System EPROCESS & 0xFFFFFFFFFFFFFFF000 के परिणाम की सामग्री कॉपी की गई थी।

इसमें वह v14 जोड़ता है जो System EPROCESS के अंतिम 3 बाइट्स हैं और फिर 0x4b8 जोड़ता है जो Windows 11 के इस संस्करण के लिए Token का ऑफसेट है, फिर उस पते की सामग्री ढूंढता है जिसमें System Token का मान सहेजा गया होगा।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Texto Descripción generada automáticamente

टोकन को मान्य करना

Texto Descripción generada automáticamente con confianza baja

याद रखें कि अंतिम 4 बिट बदले गए थे, यह महत्वपूर्ण नहीं है, इसलिए मान अभी भी मेल खाता है।

अपनी प्रक्रिया के टोकन को सिस्टम टोकन से अधिलेखित करना

दूसरी कॉल में Flag का मान 1 है क्योंकि पहली कॉल के अंत में इसे बढ़ाया गया था।

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

वहाँ हम वह क्रम देखते हैं जिसमें मान संग्रहीत होते हैं

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

पता 0xFFFFFFFF उस मान के साथ जो हमने अभी पाया है System Process Token का।

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

और HeapSpray में मेरी प्रक्रिया के Token पते का मान है जिसमें से मैं 8 घटाता हूँ। यह मान प्लस आठ लक्ष्य के रूप में उपयोग किया जाएगा, याद रखें कि आपने RAX+8 द्वारा इंगित पते पर लिखा था।

Graphical user interface, text Description automatically generated

Texto Descripción generada automáticamente

0x5000000 से शुरू होने वाले मेमोरी पते में

Interfaz de usuario gráfica Descripción generada automáticamente

हम यह भी देखते हैं कि यह दूसरे कंटेनर का नाम उपयोग करता है, क्योंकि पिछला कंटेनर सिस्टम प्रक्रिया द्वारा उपयोग किया जा रहा है और इसे फिर से नहीं खोला जा सकता या हटाया नहीं जा सकता।

फिर बग दूसरी बार उसी तरह ट्रिगर होता है जैसे पहले प्रयास में हुआ था।

यह फिर से CLFS!ClfsEarlierLsn() पर आता है।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

RDX को 0xFFFFFFFF पर सेट करते हुए

Una captura de pantalla de un celular Descripción generada automáticamente

फिर यह nt!SeSetAccessStateGenericMapping() पर आता है

Texto Descripción generada automáticamente

मेरी प्रक्रिया के Token के पते को माइनस 8 पढ़ता है जहाँ लिखा जाना है

Texto Descripción generada automáticamente

फिर SYSTEM TOKEN पढ़ता है

Texto Descripción generada automáticamente

और मेरी प्रक्रिया के Token के पते पर (वह 8 जोड़ता है), System Token लिखता है

और इस प्रकार मेरी प्रक्रिया System Token के साथ होती है

Texto Descripción generada automáticamente

टोकन लिखे जाने के बाद, हम विशेषाधिकारों की जाँच करने के लिए एक प्रक्रिया शुरू करते हैं, इस मामले में, हम Notepad.exe लॉन्च करते हैं

प्रक्रिया को system के रूप में निष्पादित करना:

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Aplicación, Word Descripción generada automáticamente

Texto Descripción generada automáticamente con confianza baja

याद रखें कि यह POC केवल Windows 11 में काम करता है, Windows 10 में यह BSOD उत्पन्न करेगा, इसलिए सही ढंग से काम करने के लिए आपको कुछ संशोधन करने होंगे, इस ब्लॉगपोस्ट में इसकी व्याख्या नहीं की गई है।

पैच को रिवर्स करना:

संरचनाओं का विश्लेषण

संरचनाएं और CLFS फ़ाइल प्रारूप पर अधिकांश दस्तावेज़ीकरण, हमने IONESCU के CLFS Internals पर उत्कृष्ट कार्य से लिया है।

हम देख सकते हैं कि ClfsBaseFilePersisted::LoadContainerQ फ़ंक्शन में एक जाँच जोड़ी गई है

Texto Descripción generada automáticamente con confianza media

जो मान जोड़ (addition) करते हैं, वे _CLFS_BASE_RECORD_HEADER संरचना से संबंधित हैं।

Escala de tiempo Descripción generada automáticamente con confianza media

ध्यान दें कि Base Block फ़ाइल के ऑफसेट 0x800 से शुरू होता है, और ऑफसेट 0x71FF पर समाप्त होता है, पहले 0x70 बाइट्स Log Block Header के अनुरूप होते हैं

एक अच्छे अभ्यास के रूप में, हम IDA पर _CLFS_LOG_BLOCK_HEADER संरचना जोड़ सकते हैं

struct _CLFS_LOG_BLOCK_HEADER

{

UCHAR MajorVersion;

UCHAR MinorVersion;

UCHAR Usn;

char ClientId;

USHORT TotalSectorCount;

USHORT ValidSectorCount;

ULONG Padding;

ULONG Checksum;

ULONG Flags;

CLFS_LSN CurrentLsn;

CLFS_LSN NextLsn;

ULONG RecordOffsets[16];

ULONG SignaturesOffset;

};

फिर हमारे पास Base Record Header (_CLFS_BASE_RECORD_HEADER) है जो फ़ाइल की शुरुआत से ऑफसेट 0x870 पर शुरू होता है और 0x1338 बाइट्स लंबा होता है।

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

यदि आप इसे IDA में आयात करना चाहते हैं, तो पहले आपको निम्नलिखित प्रकार और लापता संरचनाएँ जोड़नी होंगी

typedef GUID CLFS_LOG_ID;
typedef UCHAR CLFS_LOG_STATE;

struct _CLFS_METADATA_RECORD_HEADER

{

ULONGLONG ullDumpCount;

};

अब इसे जोड़ने के लिए तैयार है:

typedef struct _CLFS_BASE_RECORD_HEADER

{

CLFS_METADATA_RECORD_HEADER hdrBaseRecord;

CLFS_LOG_ID cidLog;

ULONGLONG rgClientSymTbl[0x0b];

ULONGLONG rgContainerSymTbl[0x0b];

ULONGLONG rgSecuritySymTbl[0x0b];

ULONG cNextContainer;

CLFS_CLIENT_ID cNextClient;

ULONG cFreeContainers;

ULONG cActiveContainers;

ULONG cbFreeContainers;

ULONG cbBusyContainers;

ULONG rgClients[0x7c];

ULONG rgContainers[0x400];

ULONG cbSymbolZone;

ULONG cbSector;

USHORT bUnused;

CLFS_LOG_STATE eLogState;

UCHAR cUsn;

UCHAR cClients;

} CLFS_BASE_RECORD_HEADER, *PCLFS_BASE_RECORD_HEADER;

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

संरचनाओं को शामिल करने के बाद, हम देखते हैं कि यह cbSymbolZone और उस पते के बीच एक जोड़ करता है जहाँ _CLFS_BASE_RECORD_HEADER समाप्त होता है। (start + 1338h)Texto, Aplicación Descripción generada automáticamente

याद रखें कि cbSymbolZone को तैयार किए गए log फ़ाइल में 0x000000F8 से 0x0001114B में संशोधित किया गया था।

(फ़ाइल का ऑफसेट 0x1b98)

0x800 (बेस ब्लॉक की शुरुआत का ऑफसेट) + 0x70 (logBlockHeader) + 0x1328 (cbsymbolZone)

0x800+0x70+0x1328 = 0x1b98

MyLog.blf फ़ाइल पर तैयार किया गया cbsymbolZone:

Tabla Descripción generada automáticamente

Imagen que contiene Texto Descripción generada automáticamente

चूंकि पैच CClfsBaseFilePersisted::LoadContainerQ फ़ंक्शन में है, हमें CClfsBaseFilePersisted ऑब्जेक्ट पर एक नज़र डालनी होगी।

CLFS!CClfsBaseFilePersisted::LoadContainerQ में ब्रेकपॉइंट सेट करें और जब CreateLogFile को तैयार फ़ाइल के हैंडल के साथ कॉल किया जाता है तो यह टूट जाएगा।

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Base Log Record (_CLFS_BASE_RECORD_HEADER) का पता प्राप्त करने के लिए CClfsBaseFile::GetBaseLogRecord फ़ंक्शन को कॉल करें

Graphical user interface, application, timeline Description automatically generated

RAX _CLFS_BASE_RECORD_HEADER पते की ओर इशारा करेगा

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

मेमोरी में _CLFS_BASE_RECORD_HEADER संरचना और cbsymbolZone फ़ील्ड 0x1328 बाइट्स आगे पर ध्यान दें

Imagen que contiene Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

r14 "this" के अनुरूप संरचना को संग्रहीत करता है, जो कि CClfsBaseFilePersisted है क्योंकि यह CClfsBaseFilePersisted::LoadContainerQ. फ़ंक्शन का this है।

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

मेमोरी में CClfsBaseFilePersisted संरचना:

Texto Descripción generada automáticamente

तो, चलिए इसके फ़ील्ड्स को पूरा करने के लिए लंबाई 0x21c0 वाली एक संरचना बनाते हैं जब तक हम इसे रिवर्स करते हैं (यह एक अनिर्देशित संरचना है) हम इसे struct_CClfsBaseFilePersisted कहेंगे

Tabla Descripción generada automáticamente con confianza media

फ़ंक्शन CClfsBaseFile::GetBaseLogRecord() के अंदर _CLFS_BASE_RECORD_HEADER का पॉइंटर मिलता है। और हम जानते हैं कि उस फ़ंक्शन में "this" संरचना है: struct_CClfsBaseFilePersisted।

Escala de tiempo Descripción generada automáticamente con confianza media

दो फ़ील्ड्स पढ़ें (ऑफसेट 0x28 और 0x30)

Interfaz de usuario gráfica, Aplicación, Tabla Descripción generada automáticamente

फ़ील्ड 0x28 एक word है और इसका मान 6 है, इसलिए हम संरचना में प्रकार को word में बदलते हैं।

Texto Descripción generada automáticamente

Texto Descripción generada automáticamente con confianza media

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

अभी के लिए, हम इसे स्थिरांक 6 (const_6) में बदलते हैं

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

दस्तावेज़ीकरण के अनुसार, 6 ब्लॉकों की संख्या CLFS_METADATA_BLOCK_COUNT होगी। फ़ील्ड इस मान को संदर्भित कर सकता है।

और वह पॉइंटर ऑफसेट 0x30 पर है।

Tabla Descripción generada automáticamente

ध्यान दें कि वहाँ दिखाया गया आकार लंबाई 0x10 वाले हेडर को शामिल करता है

Texto Descripción generada automáticamente

Forma Descripción generada automáticamente con confianza media

जब ExAllocatePoolWithTag फ़ंक्शन को कॉल किया जाता है, तो कुछ बाइट्स का अनुरोध किया जाता है, लेकिन हेडर शामिल नहीं होता है, इसलिए, कॉल में 0x90 बाइट्स (0xa0 – 0x10) का अनुरोध किया जाएगा।

+30h] टेक्स्ट द्वारा खोज करने पर, ऑफसेट 0x30 पर लिखने वाले निर्देशों की एक लंबी सूची मिलती है, लेकिन सूची को CClfsBaseFilePersisted ऑब्जेक्ट के प्रकार द्वारा फ़िल्टर करने पर कुछ ही परिणाम बचते हैं और तुरंत पता चलता है कि वह आकार कहाँ आवंटित किया गया है, और वही टैग। (टिप: Create और Initialize फ़ंक्शन नाम, हमेशा देखने वाले पहले होते हैं)

Texto Descripción generada automáticamente con confianza baja

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

चूंकि हम अभी भी नाम नहीं जानते हैं, हम इसे pool_0x90 रखेंगे, जो एक और अनिर्देशित संरचना है, और हम उस आकार की एक संरचना बनाएंगे।

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Tabla Descripción generada automáticamente

मेमोरी में pool_0x90 के अपने ऑफसेट 0x30 पर एक और पॉइंटर है।

Aplicación, Tabla Descripción generada automáticamente con confianza media

यह अन्य पॉइंटर फ़ाइल में बेस ब्लॉक की ओर इशारा करता है (बेस ब्लॉक ऑफसेट 0x800 पर शुरू होता है)

Forma Descripción generada automáticamente

A picture containing calendar Description automatically generated

छवि Zscaler ब्लॉगपोस्ट से ली गई है:

Graphical user interface, application, email Description automatically generated

आवंटन बहुत बड़ा है, क्योंकि इसमें पूरा बेस ब्लॉक होता है।

Text Description automatically generated

Graphical user interface, text, application Description automatically generated

इसलिए, हम आकार 0x7a00 की एक नई संरचना बनाएंगे और इसे BASE_BLOCK कहेंगे

Graphical user interface, text, application Description automatically generated

पहले 70 बाइट्स जिन्हें हम पहले से जानते थे, _CLFS_LOG_BLOCK_HEADER के अनुरूप हैं और अगले 0x1338 _CLFS_BASE_RECORD_HEADER के अनुरूप हैं।

Text Description automatically generated

इसलिए, बेस ब्लॉक की शुरुआत को अगले रिकॉर्ड के ऑफसेट (जो 0x70 है) के साथ जोड़ने पर, हमें _CLFS_BASE_RECORD_HEADER मिलता है

Application Description automatically generated with low confidence

मेमोरी पर _CLFS_BASE_RECORD_HEADER।

Calendar Description automatically generated

उसी CClfsBaseFilePersisted ऑब्जेक्ट के अन्य तरीकों को देखते हुए, CClfsBaseFilePersisted::AddContainer में आपको CClfsBaseFile::GetBaseLogRecord के साथ _CLFS_BASE_RECORD_HEADER का पता भी मिलता है।

Text Description automatically generated

इसके बाद, cbOffset का उपयोग करके CClfsBaseFile::OffsetToAddr को कॉल करें, यह _CLFS_CONTAINER_CONTEXT का पता प्राप्त करता है, और cboffset को rgbcontainers सरणी में संग्रहीत करता है जो _CLFS_BASE_RECORD_HEADER के ऑफसेट 0x328 पर है।

Graphical user interface, application Description automatically generated

CClfsBaseFile::OffsetToAddr फ़ंक्शन का उपयोग ऑफसेट से संरचनाओं के पते खोजने के लिए किया जाता है

Graphical user interface, text, application Description automatically generated

इस बिंदु पर, कंटेनर ऑफसेट जो 0x328 पर संग्रहीत किया जाएगा वह अभी भी 0 है, क्योंकि हमने अभी तक एक कंटेनर नहीं जोड़ा है।

Background pattern Description automatically generated with low confidence

PoC CreateLogFile को दो बार कॉल करता है, पहली बार malformed फ़ाइल MyLog.blf के साथ और दूसरी बार सामान्य MyLogxxx.blf फ़ाइल के साथ, इसलिए हमें उपरोक्त सभी स्थानों पर डिबगिंग को दो बार रोकना होगा और दोनों फ़ाइलों के लिए उपरोक्त संरचनाओं के पते नोटपैड में नोट करने होंगे।

Text Description automatically generated

आइए उस पर ब्रेकपॉइंट सेट करके और वहाँ चलाकर CLFS!CClfsLogFcbPhysical::AllocContainer तक थोड़ा आगे बढ़ते हैं।

जब POC पर AddLogContainer() पहुँच जाता है, तो हम ब्रेकपॉइंट पर रुक जाते हैं।

A picture containing application Description automatically generated

चलिए CClfsBaseFilePersisted::AddContainer+176 पर भी एक ब्रेकपॉइंट सेट करते हैं, जहाँ हमने पहले देखा था कि _CLFS_CONTAINER_CONTEXT संरचना का ऑफसेट और पॉइंटर मिलेगा।

A screenshot of a computer Description automatically generated with medium confidence

Graphical user interface, text, application Description automatically generated

जब डीबगर टूटता है, तो हम देख सकते हैं कि ऑफसेट 0x1468 है।

Text Description automatically generated

RAX में _CLFS_CONTAINER_CONTEXT संरचना का पता लौटेगा।

Graphical user interface, text, application, table Description automatically generated

संरचना अभी भी खाली है क्योंकि कंटेनर अभी तक नहीं जोड़ा गया था।

Text Description automatically generated

ध्यान दें कि SignatureOffset=0x50 मान जो हमने malformed फ़ाइल में ऑफसेट 0x868 पर लिखा था, बेस ब्लॉक की शुरुआत से 0x800 घटाने पर, ऑफसेट 0x68 पर _CLFS_LOG_BLOCK_HEADER संरचना में होगा।

Graphical user interface, text, application Description automatically generated

Text, letter Description automatically generated

जब PoC malformed फ़ाइल का उपयोग करके AddLogContainer() फ़ंक्शन को कॉल करता है, तो _CLFS_LOG_BLOCK_HEADER के ऑफसेट 0x68 पर, वहाँ लिखे गए 0x50 मान के बजाय, मेमोरी में वर्तमान में 0xFFFF0050 है।

A picture containing text Description automatically generated

किसी बिंदु पर, वह मान प्रोग्राम द्वारा बदल दिया गया था, यह देखने के लिए कि यह कब हुआ, अगले निष्पादन में, हम राइट पर मेमोरी ब्रेकपॉइंट सेट करेंगे।

ऑफसेट r15 + 0x328 पर संग्रहीत है (r15 _CLFS_BASE_RECORD_HEADER संरचना की ओर इशारा करता है)

Text Description automatically generated with medium confidence

Graphical user interface Description automatically generated with low confidence

RBX ऑफसेट 0x1468 संग्रहीत करता है।

A picture containing calendar Description automatically generated

इसलिए, बेस ब्लॉक पते + 0x70 + ऑफसेट 0x1468 में जो हमें पता चला, वहाँ CLFS_CONTAINER_CONTEXT कंटेनर का पता होगा।

Text Description automatically generated

ऑफसेट 0x18 पर CLFS_CONTAINER_CONTEXT संरचना में pContainer पॉइंटर होगा जो वहाँ संग्रहीत किया जाएगा, हम राइट पर ब्रेकपॉइंट सेट कर सकते हैं और देख सकते हैं कि यह कब लिखा जाता है।

Text Description automatically generated

A picture containing text Description automatically generated

यह वह पॉइंटर है जिसे हमें करप्ट करना होगा क्योंकि जिस फ़ंक्शन में कमजोरी है, वह पहले CLFS_CONTAINER_CONTEXT पढ़ता है, फिर इसे r15 में ले जाता है और फिर r15+18 का मान पढ़ता है, जो यह पॉइंटर है जिस पर हमने अभी राइट पर ब्रेकपॉइंट सेट किया है।

Graphical user interface, application, table Description automatically generated

Graphical user interface, application, Word Description automatically generated

यह pContainer को struct_CClfsBaseFilePersisted संरचना के ऑफसेट 0x1c0 पर संग्रहीत करता है।

Text, application, whiteboard Description automatically generated

कई बार रुकने के बाद, हम उस क्षण पर पहुँचते हैं जहाँ यह करप्ट हो जाता है। पॉइंटर पते का शीर्ष FFs से शून्य में बदल दिया गया है।

Calendar Description automatically generated

यह तब होता है जब malformed फ़ाइल का दूसरा AddLogContainer() कॉल किया जाता है, पिछले MyLogxxx का पॉइंटर करप्ट हो जाता है।

समस्या इसलिए होती है क्योंकि SignaturesOffset, जो 0x50 होना चाहिए, अब 0xFFFF0050 है, इसलिए यह बाद में आने वाले memset में सीमा से बाहर लिखने की अनुमति देता है।

Graphical user interface, text, application Description automatically generated

Graphical user interface, text Description automatically generated

“pContainer” पॉइंटर को करप्ट करना:

memset() फ़ंक्शन नीचे स्थित _CLFS_CONTAINER_CONTEXT संरचना को करप्ट करने जा रहा है, यह संरचना MyLogxxx फ़ाइल के अनुरूप है, क्योंकि जब बनाई गई थीं, तो यह उन्हें एक दूसरे से 0x11000 बाइट्स की दूरी पर स्थित करता था।

इस तरह, यह ठीक से गणना करता है कि अगली संरचना में कहाँ लिखना है और पॉइंटर के शीर्ष को शून्य कर देता है, ताकि यह उपयोगकर्ता हीप की ओर इशारा करे जहाँ HeapSspray बनाया गया था।

malformed फ़ाइल की बेस ब्लॉक संरचना MyLogxxx फ़ाइल की तुलना में केवल 0x11000 पहले है।

Malformed:

Shape Description automatically generated

MyLogxxx

A picture containing text Description automatically generated

RCX, RDX से छोटा है क्योंकि 0xFFFF0050 जोड़ा गया था, 0x50 के बजाय जैसा कि होना चाहिए।

Graphical user interface, text, application Description automatically generated

और हम memset() फ़ंक्शन पर पहुँच गए, जो 0xb0 बाइट्स की मात्रा को शून्य से सेट करने के लिए है, RCX MyLogxxx फ़ाइल की CLFS_CONTAINER_CONTEXT संरचना की ओर इशारा करता है, विशेष रूप से pContainer के पाँच उच्च बाइट्स की ओर।

Text Description automatically generated

यह पॉइंटर पहले बाइट्स को अधिलेखित करके करप्ट हो जाएगा:

Text Description automatically generated

पहले HeapSpray के माध्यम से हमारे द्वारा नियंत्रित मेमोरी पते की ओर इशारा करते हुए रहता है

Text Description automatically generated

A picture containing text Description automatically generated

फिर, MyLogxxx फ़ाइल का हैंडल बंद हो जाएगा, और CClfsBaseFilePersisted::RemoveContainer पर पहुँचता है, अंततः कमजोरी ट्रिगर होती है।

Text, application Description automatically generated with medium confidence

पैच की समीक्षा

अब जब हमारे पास अधिक जानकारी है, तो हम देखते हैं कि यहाँ यह Base_Block.LOG_BLOCK_HEADER.SignaturesOffset और Base_Block. .LOG_BLOCK_HEADER.TotalSectorCount पढ़ता है

पैच के पहले भाग में SignaturesOffset 0x7a00 से अधिक नहीं होना चाहिए, हमारे मामले में यह मूल रूप से 0x50 था, अगर यह 0x7a00 से अधिक मान के साथ आता है तो यह हमें बाहर निकाल देगा।

A picture containing diagram Description automatically generated

पैच की गई मशीन में PoC चलाने पर, यह 0x50 की तुलना 0x7a00 से करता है और चूंकि यह छोटा है, यह जारी रहता है।

Text Description automatically generated

निम्नलिखित ब्लॉक में, malformed cbSymbolZone को _CLFS_BASE_RECORD_HEADER के अंतिम पते के मान में जोड़ा जाता है और यह योग result_1 में संग्रहीत किया जाता है।

Text Description automatically generated

फिर, Base_Block का पता SignatureOffset मान के साथ जोड़ा जाता है, जो सामान्य फ़ाइल में 0x7980 है।

Text Description automatically generated

base_block का अधिकतम पता 0x7a00 है, अब SymbolZone को सीमा से पहले 0x80 तक अनुमति है।

यह इसे result_2 में संग्रहीत करेगा, यानी यह base block के अंदर SymbolZone के लिए अधिकतम सीमा होगी, फिर यह दोनों परिणामों की तुलना करता है, यदि पहला दूसरे से बड़ा है, तो इसका मतलब है कि यह सीमा से बाहर चला गया।

Text Description automatically generated

Text Description automatically generated

जाहिर है पहला सदस्य दूसरे से बड़ा होगा और यह जारी नहीं रहेगा, क्योंकि cbSymbolZone + _CLFS_BASE_RECORD_HEADER के अंतिम पते का पहला योग सीमा (जो result_2 है) से अधिक है और "आउट ऑफ बाउंड्स" की ओर ले जाता है।

Graphical user interface, text, application Description automatically generated

SignatureOffset को करप्ट करना

आखिरी चीज़ जो हमें समझनी होगी वह यह है कि SignatureOffset का मान 0x50 कहाँ 0xFFFF0050 बन जाता है।तो, चलिए फिर से शुरू करते हैं, रीबूट करते हैं और CLFS!CClfsBaseFilePersisted::LoadContainerQ पर रुकते हैं, जहाँ मान अभी तक मेमोरी में बदला नहीं गया है और अभी भी 0x50 है।

SignatureOffset के ऑफसेट 0x68 पर एक एक्सेस ब्रेकपॉइंट सेट करें।

कैलेंडर विवरण स्वचालित रूप से जनरेट किया गया

और कई बार रुकने के बाद, हम सही क्षण का पता लगाते हैं जब यह ClfsEncodeBlockPrivate में मान को संशोधित करता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

यह फ़ंक्शन पैच नहीं किया गया है, इसलिए यह 0x50 के कम मान और बाकी मानों के हेरफेर किए जाने के कारण उत्पन्न व्यवहार हो सकता है।

तैयार किए गए मानों में, हम ccoffsetArray मान देख सकते हैं, जिसका नाम _CLFS_BASE_RECORD_HEADER संरचना में rgClients है और यह उन ऑफसेट्स की सरणी को दर्शाता है जो Client Context ऑब्जेक्ट की ओर इंगित करते हैं।

rgClients फ़ील्ड _CLFS_BASE_RECORD_HEADER संरचना के ऑफसेट 0x138 (0x9a8-0x800-0x70) पर स्थित है।

ग्राफ़िकल यूज़र इंटरफ़ेस, तालिका विवरण स्वचालित रूप से जनरेट किया गया

टेक्स्ट विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

PoC में, यह मान एक नकली क्लाइंट कॉन्टेक्स्ट ऑब्जेक्ट को इंगित करने के लिए विकृत किया गया है, जिसे FakeClientContext कहा जाता है।टेक्स्ट, व्हाइटबोर्ड विवरण स्वचालित रूप से जनरेट किया गया

कंप्यूटर का स्क्रीनशॉट मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

यह Client Context संरचना _CLFS_CLIENT_CONTEXT है।

struct _CLFS_CLIENT_CONTEXT

{

CLFS_NODE_ID cidNode;

CLFS_CLIENT_ID cidClient;

USHORT fAttributes;

ULONG cbFlushThreshold;

ULONG cShadowSectors;

ULONGLONG cbUndoCommitment;

LARGE_INTEGER llCreateTime;

LARGE_INTEGER llAccessTime;

LARGE_INTEGER llWriteTime;

CLFS_LSN lsnOwnerPage;

CLFS_LSN lsnArchiveTail;

CLFS_LSN lsnBase;

CLFS_LSN lsnLast;

CLFS_LSN lsnRestart;

CLFS_LSN lsnPhysicalBase;

CLFS_LSN lsnUnused1;

CLFS_LSN lsnUnused2;

CLFS_LOG_STATE eState;

union

{

HANDLE hSecurityContext;

ULONGLONG ullAlignment;

};

};

eState मान संरचना की शुरुआत से ऑफसेट 0x78 पर है, तैयार की गई फ़ाइल में 0x23a0+0x78 पर।

टेक्स्ट विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

चार्ट, स्कैटर चार्ट विवरण स्वचालित रूप से जनरेट किया गया

यह मान लॉग की स्थिति दर्शाता है।

typedef UCHAR CLFS_LOG_STATE, *PCLFS_LOG_STATE;
const CLFS_LOG_STATE CLFS_LOG_UNINITIALIZED = 0x01;
const CLFS_LOG_STATE CLFS_LOG_INITIALIZED = 0x02;
const CLFS_LOG_STATE CLFS_LOG_ACTIVE = 0x04;
const CLFS_LOG_STATE CLFS_LOG_PENDING_DELETE = 0x08;
const CLFS_LOG_STATE CLFS_LOG_PENDING_ARCHIVE = 0x10;
const CLFS_LOG_STATE CLFS_LOG_SHUTDOWN = 0x20;
const CLFS_LOG_STATE CLFS_LOG_MULTIPLEXED = 0x40;
const CLFS_LOG_STATE CLFS_LOG_SECURE = 0x80;

यह मान CLFS_LOG_STATE CLFS_LOG_SHUTDOWN =0x20 पर सेट है।

दूसरा विकृत मान fAttributes है, जो बेस लॉग फ़ाइल से जुड़े FILE_ATTRIBUTE फ़्लैग्स के सेट से संबंधित है (जैसे System और Hidden)।

ग्राफ़िकल यूज़र इंटरफ़ेस विवरण कम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

टेक्स्ट, अक्षर विवरण स्वचालित रूप से जनरेट किया गया

चूँकि फ़ील्ड एक बाइट पहले 0xa पर शुरू होती है और दो बाइट्स तक फैली हुई है, fAttributes का मान 0x100 है।

तालिका वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

अंत में, blocknameoffset मान है जो ऑफसेट 0x1bb8 की ओर इंगित करता है, मेरा मतलब है, 0x78 और 0x800 जोड़ने पर यह फ़ाइल के ऑफसेट 0x2428 की ओर इंगित करता है।

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

टेक्स्ट, अक्षर विवरण स्वचालित रूप से जनरेट किया गया

ध्यान दें कि Client Context का ऑफसेट 0x1b30 है।

तालिका विवरण स्वचालित रूप से जनरेट किया गया

तो, Client Context ऑफसेट 0x23a0 पर है।

टेक्स्ट विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

तालिका विवरण स्वचालित रूप से जनरेट किया गया

और ठीक 0x10 पहले, यह blocknameoffset के अनुरूप मान है।

टेक्स्ट, अक्षर विवरण स्वचालित रूप से जनरेट किया गया

तालिका विवरण कम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

जो नाम वाली स्ट्रिंग की ओर इंगित करेगा।

आखिरी मान blockattributeoffset है, जो 0x2394 पर Client Context से 0xC पहले है।

तालिका विवरण स्वचालित रूप से जनरेट किया गया

ये अंतिम दो मान Client Context से पहले 0x30 बाइट लंबी संरचना से संबंधित हैं, जिसे _CLFSHASHSYM कहा जाता है।

typedef struct _CLFSHASHSYM
{
CLFS_NODE_ID cidNode;
ULONG ulHash;
ULONG cbHash;
ULONGLONG ulBelow;
ULONGLONG ulAbove;
LONG cbSymName;
LONG cbOffset;
BOOLEAN fDeleted;
} CLFSHASHSYM, *PCLFSHASHSYM;

आरेख वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

वे _CLFSHASHSYM संरचना की शुरुआत से 0x20 और 0x24 बाइट्स पर हैं, इसलिए _CLFSHASHSYM संरचना में PoC में blockNameOffset नामक मान cbSymName फ़ील्ड है और blockAttributteoffset cbOffset फ़ील्ड है।

टेक्स्ट वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

टेक्स्ट विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

ये विकृत मान हैं, अब हमें यह देखना है कि ये हमारे SignaturesOffset को 0x50 मान से 0xFFFF0050 में बदलने को कैसे प्रभावित करते हैं।

आइए CClfsBaseFile::AcquireClientContext() फ़ंक्शन पर एक नज़र डालते हैं, जिसे क्लाइंट कॉन्टेक्स्ट लौटाना चाहिए।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन, ईमेल विवरण स्वचालित रूप से जनरेट किया गया

यह CClfsBaseFile::GetSymbol को चौथे आर्ग्युमेंट के साथ कॉल करता है, जो _CLFS_CLIENT_CONTEXT ** होगा, जहाँ यह Client Context का पॉइंटर संग्रहीत करेगा।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

CClfsBaseFile::GetSymbol फ़ंक्शन के अंदर हम विकृत ccoffsetArray ऑफसेट को CClfsBaseFile::OffsetToAddr में पास करते हैं और क्लाइंट कॉन्टेक्स्ट का पता प्राप्त करते हैं, आइए वहाँ एक ब्रेकपॉइंट सेट करें ताकि यह CreatelogFile . के साथ बनाई गई फ़ाइल को कॉल करते समय रुक जाए।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

वहाँ यह ccoffsetArray तैयार किए गए आर्ग्युमेंट के साथ रुका हुआ है।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

तालिका विवरण स्वचालित रूप से जनरेट किया गया

CClfsBaseFile::OffsetToAddr फ़ंक्शन गलत Client Context लौटाता है।

ग्राफ़िकल यूज़र इंटरफ़ेस वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

और जाँचता है कि cbOffset का मान शून्य नहीं है, क्योंकि RAX में मौजूद _CLFS_CLIENT_CONTEXT संरचना से पहले 0xC पाया जाता है।

कंप्यूटर का स्क्रीनशॉट विवरण स्वचालित रूप से जनरेट किया गया

टेक्स्ट वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

फिर यह cbOffset की तुलना **ccoffsetArray (**जो RSI में है) से करता है, उन्हें बराबर होना चाहिए, अन्यथा हमें एक त्रुटि मिलेगी।

कंप्यूटर का स्क्रीनशॉट विवरण स्वचालित रूप से जनरेट किया गया

यह यह भी जाँचता है कि cbSymName, cbOffset+0x88, के बराबर हो, अन्यथा हमें भी एक त्रुटि मिलेगी।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

और अंत में, यह cidClient बाइट की तुलना शून्य से करता है।

आरेख वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

यदि ये सभी जाँचें सफल होती हैं, तो client context सहेज लिया जाएगा।

कंप्यूटर का स्क्रीनशॉट विवरण स्वचालित रूप से जनरेट किया गया

फ़ंक्शन r14 का आउटपुट Client Context की ओर इंगित करता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

CClfsLogFcbPhysical::Initialize से बाहर निकलते समय हमारे पास CLFS_CLIENT_CONTEXT का पता होगा।

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

अब यह fAttributes (0x100) का मान पढ़ता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

यह फ़ंक्शन CClfsLogFcbPhysical क्लास से संबंधित है।

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

जिसे यहाँ आवंटित किया गया था, और इसका आकार 0x15d0 है और इसका टैग “ClfC” है।

टेक्स्ट विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

आइए हम जो रिवर्स कर रहे हैं उसे संग्रहीत करने के लिए एक संरचना बनाते हैं, हम इसे: struct_CClfsLogFcbPhysical. कहेंगे।

तालिका वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

ध्यान दें कि 0x2b0 पर यह CClfsBaseFilePersisted संरचना का पता सहेजता है।

एप्लिकेशन वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

संरचना में कई मान सहेजने के बाद, यह एक महत्वपूर्ण भाग पर जाता है, यह eState को 0x20 के साथ जाँचता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन, तालिका विवरण स्वचालित रूप से जनरेट किया गया

चूँकि तैयार किया गया मान 0x20 था, परीक्षण 1 लौटाएगा।

तालिका विवरण स्वचालित रूप से जनरेट किया गया

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

हम देखते हैं कि कंस्ट्रक्टर में vtable में है।

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

यह जाँचेगा कि फ़ाइल multiplexed है या नहीं।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

तो, यह वांछित मार्ग से जाता है, CClfsLogFcbPhysical::ResetLog तक पहुँचता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

टेक्स्ट, एप्लिकेशन, तालिका विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

कई फ़ील्ड शून्य पर आरंभ किए जाते हैं, एक को छोड़कर जो 0xFFFFFFFF00000000 पर आरंभ किया जाता है।

ग्राफ़िकल यूज़र इंटरफ़ेस विवरण कम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

यहाँ Client Context प्राप्त करता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

यह मान 0xFFFFFFFF00000000 संग्रहीत करता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

कैलेंडर वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

यह 0xFFFFFFFF को ऑफसेट 0x5c पर लिखता है, जो CLFS_LSN lsnRestart.ullOffset का उच्च भाग है।

टेक्स्ट विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, अक्षर विवरण स्वचालित रूप से जनरेट किया गया

अब हम ClfsEncodeBlockPrivate() फ़ंक्शन निष्पादित करते हैं, जो जैसा हमने पहले देखा है, 0x50 को 0xFFFF0050 से अधिलेखित करने के लिए ज़िम्मेदार है।

वहाँ यह SignatureOffset = 0x50 का मान पढ़ता है, जो अभी भी वैसा ही है जैसा हमने विकृत फ़ाइल में रखा था, और इसे CLFS_LOG_BLOCK_HEADER की शुरुआत में जोड़ता है।

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

यह एक लूप है जो 2 बाइट्स लिख रहा है, जैसे SignatureOffset किसी सही मान की ओर इंगित करने के बजाय, जो सामान्य फ़ाइल में एक उच्च मान होता है, उदाहरण के लिए 0x3f8 जो इसे आगे लिखने के लिए प्रेरित करता है, यहाँ यह उसी CLFS_LOG_BLOCK_HEADER में लिखेगा।

विचार लिखने के गंतव्य को बदलकर SignatureOffset मान को भ्रष्ट करने का प्रयास करना है।

सामान्य फ़ाइल

तालिका विवरण स्वचालित रूप से जनरेट किया गया

इस बिंदु पर, यह लूप करना शुरू कर देगा और दो बाइट्स लिखेगा।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

लूप से बाहर निकलने के लिए काउंटर को 0x3d मान तक पहुँचना चाहिए।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

RCX 0x200 से बढ़ रहा है, हम पहले से ही तीसरे चक्र में हैं, और इसका मान 0x600 है।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

पुनरावृत्ति 0xe में, RCX 0x1a00 है।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

कैलेंडर वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

वहीं उसने 0xFFFFFFFF000000 लिखा था।

ग्राफ़िकल यूज़र इंटरफ़ेस, टेक्स्ट, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

तालिका विवरण मध्यम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

यह अंतिम दो बाइट्स FFFF पढ़ रहा है।

टेक्स्ट विवरण स्वचालित रूप से जनरेट किया गया

और फिर इसे R8 में कॉपी करेगा।

कैलेंडर वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

कैलेंडर वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

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

CClfsBaseFilePersisted::AllocSymbol में, वही योग जो memset के गंतव्य को प्राप्त करने वाला है, जो cbSymbolZone + CLFS_BASE_RECORD_HEADER का अंतिम पता है, इसकी तुलना पहले Base_block + 0xFFFF0050 से करता है, इसलिए समीकरण के दोनों ओर भ्रष्ट मान हैं।

CbSymbolZone= 0x1114B

यह विकृत मान है जो CLFS_BASE_RECORD_HEADER के अंतिम पते में जोड़े जाने पर इसे सीमा से बाहर लिखने के लिए प्रेरित करेगा, और तुलना का दूसरा सदस्य जो Base Block + SignatureOffset का पता होना चाहिए, वह SignatureOffset =0xFFFF0050 बना रहता है, जो इस जाँच को पास करने और memset() में सीमा से बाहर लिखने तथा पॉइंटर के शीर्ष को शून्य करने की अनुमति देता है, जो हमारे HeapSpray की ओर इंगित करता रहेगा।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन, तालिका विवरण स्वचालित रूप से जनरेट किया गया

चूँकि RCX, RDX से छोटा है।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

जैसा कि हमने पहले देखा है। (मान भिन्न हो सकते हैं क्योंकि वे पिछले निष्पादन से संबंधित हैं।)

यह पॉइंटर को भ्रष्ट कर देगा, उच्चतम बाइट्स को 0 पर सेट कर देगा।

तालिका विवरण स्वचालित रूप से जनरेट किया गया

इसे एक मेमोरी क्षेत्र की ओर इंगित करता हुआ छोड़ देता है जिसे हम HeapSpray के माध्यम से नियंत्रित करते हैं।

कंप्यूटर का स्क्रीनशॉट कम विश्वास के साथ स्वचालित रूप से जनरेट किया गया

तालिका विवरण स्वचालित रूप से जनरेट किया गया

तो, जब कमज़ोरी ट्रिगर होती है, हम CClfsBaseFilePersisted::RemoveContainer तक पहुँचते हैं।

ग्राफ़िकल यूज़र इंटरफ़ेस वाली तस्वीर विवरण स्वचालित रूप से जनरेट किया गया

वहाँ पहले से भ्रष्ट पॉइंटर होगा और जैसा हमने पहले देखा, इसका शोषण किया जा सकता है।

ग्राफ़िकल यूज़र इंटरफ़ेस, एप्लिकेशन विवरण स्वचालित रूप से जनरेट किया गया

इस बिंदु पर हमने बग का शोषण कर लिया है, यह उन फ़ंक्शनों को नियंत्रित करने की ओर ले जाता है जो SYSTEM टोकन को पढ़ने और अपनी प्रक्रिया में लिखने की अनुमति देते हैं, ताकि स्थानीय विशेषाधिकार वृद्धि प्राप्त की जा सके।

हमें उम्मीद है कि यह आपको उपयोगी लगेगा, यदि आपको कोई संदेह है तो आप हमसे [email protected] और [email protected] पर संपर्क कर सकते हैं।

आनंद लीजिए!

टूल डाउनलोड करें