
CVE-2020-15368, उर्फ "एक संवेदनशील ड्राइवर का शोषण कैसे करें"
CVE-2020-15368 के लिए शोषण और प्रूफ ऑफ कॉन्सेप्ट (PoC)। Asrock ने अपने RGB नियंत्रक कॉन्फ़िगरेशन टूल के लिए rweverything ड्राइवर को पुनः पैकेज किया और उस पर हस्ताक्षर किए। उन्होंने अपने ioctls को एन्क्रिप्ट करके इसे "सुरक्षित" किया... lol। हमें यह CVE पिछली गर्मियों में दुर्घटनावश मिला था, और जहाँ तक मुझे पता है, ड्राइवर अभी भी पैच नहीं किया गया है। प्रभाव निश्चित रूप से कर्नेल में मनमाना कोड निष्पादन आदि है। तो इस "0day" का आनंद लें lol।
यदि आप मेरे साथ इस बात पर बहस करना चाहते हैं कि क्या यह एक वास्तविक BONA FIDE CVE है, तो कृपया मुझसे Twitter पर संपर्क करने में संकोच न करें, हम सार्वजनिक सोशल मीडिया पर एक बड़ी लड़ाई कर सकते हैं और यह इसमें शामिल सभी लोगों के लिए वास्तव में रोमांचक होगा! मैं इस बग के लिए एक डोमेन भी खरीदूंगा यदि आप ऐसा चाहते हैं। यह सब मार्केटिंग के बारे में है!!!!
वैसे भी, यह बग काफी बेकार है, इसलिए मैं इसे एक ट्यूटोरियल के रूप में उपयोग करूंगा कि कैसे एक सामान्य कमजोर ड्राइवर को हैक किया जाए। इसलिए यह पोस्ट शुरुआती लोगों के लिए है। आप सीखेंगे कि एक कमजोर ड्राइवर का शोषण कैसे किया जाता है। इस तरह के और भी कई बेकार ड्राइवर मौजूद हैं। दुनिया आपकी सीप है। मज़े करें
अस्वीकरण: यह प्रकाशन केवल शैक्षिक उद्देश्यों के लिए प्रदान किया गया है। पाठक की जिम्मेदारी है कि वह सभी लागू स्थानीय, राज्य और संघीय कानूनों का पालन करे। इस प्रकाशन के लेखक कोई देयता नहीं मानते हैं और इस प्रकाशन में निहित सॉफ़्टवेयर के किसी भी दुरुपयोग या क्षति के लिए जिम्मेदार नहीं हैं।
क्वारंटाइन में फँसे हुए, मेरे रूममेट (Pear0, Codetector) और मैं Pear0 के नए Asrock मदरबोर्ड पर बेवकूफी कर रहे थे। चमकीले लाल LED बेहद कष्टप्रद थे और उन्हें Linux पर कॉन्फ़िगर करना संभव नहीं था। इस प्रकार हमारी योजना थी कि इसे नियंत्रित करने वाले Windows ड्राइवर को रिवर्स करें और Linux पर I/O ऑपरेशन को दोहराएं।
लंबी कहानी को संक्षेप में, हमें यह समझने में अधिक समय नहीं लगा कि ड्राइवर वास्तव में एक सामान्य ड्राइवर है जो किसी भी चीज़ तक मनमाना पढ़ने/लिखने की पहुंच प्रदान करता है। इसमें CR3, CR4 जैसे नियंत्रण रजिस्टर, भौतिक मेमोरी आदि शामिल हैं। इस प्रकार के ड्राइवर डिबगिंग टूल के रूप में उपयोग के लिए अभिप्रेत हैं और विक्रेता की वेबसाइट स्पष्ट रूप से ऐसा बताती है।

हमने सोचा कि यह बेहद मज़ेदार है। पहली बार जब आप किसी कंप्यूटर को ट्रिपल फॉल्ट करके यूजरस्पेस से हार्ड रीबूट कराते हैं तो यह काफी रोमांचक होता है। (शायद बीसवीं बार कम रोमांचक।) वैसे भी, हमने बग की सूचना दी और फिर एक साल के लिए इसे भूल गए।
एक कर्नेल नौसिखिए के रूप में, मैं सोच रहा था कि ड्राइवर को कैसे लोड और इंटरैक्ट किया जाए। पता चला कि यह बेहद आसान है।
आप Process Hacker में ड्राइवर के लिए एक सर्विस बना सकते हैं (स्पष्ट रूप से, ड्राइवर लोड करने के लिए एडमिन की आवश्यकता होती है)। फिर आप बस राइट-क्लिक करके इसे शुरू कर सकते हैं। हाँ, यह वास्तव में इतना सरल है।

हम अपने डिवाइस ऑब्जेक्ट को WinObjEx64 में देख सकते हैं।

हम FileTest में डिवाइस के साथ खेल भी सकते हैं।


ये तीनों टूल अद्भुत हैं, विशेषकर PH और FileTest। ये एक स्विस आर्मी नाइफ की तरह हैं और हर Windows रिवर्सर के टूलबॉक्स में होने चाहिए। उदाहरण के लिए, मेरी समझ से Jonas L ने FileTest में बेवकूफी करते हुए अनगिनत Windows LPE कमजोरियाँ पाई हैं। तो Windows के पास वास्तव में बेवकूफी करने के लिए कुछ बेहतरीन टूल हैं। काश Linux पर भी यह चीज़ होती।
Rweverything में एक ioctl है जो एक ioctl को पैरामीटर के रूप में लेता है, जो यह नियंत्रित करता है कि कौन सा ऑपरेशन करना है (मेमोरी पढ़ना, मेमोरी लिखना, MSR पढ़ना, आदि), और कुछ ऑपरेशन-विशिष्ट पैरामीटरों का एक यूनियन जैसे स्रोत पता, गंतव्य पता आदि। जब हम दोनों ड्राइवरों के कोड की तुलना करते हैं:

🤔🤔🤔🤔🤔🤔🤔🤔🤔
फिर भी, ड्राइवर अस्पष्टता के माध्यम से सुरक्षा का एक घटिया प्रयास करता है, जिसमें आवश्यकता होती है कि सभी ioctl कॉल को हार्डकोडेड AES कुंजी के साथ उपयुक्त रूप से एन्क्रिप्ट किया जाए। कोड (कुछ सफाई के बाद) इस प्रकार दिखता है:
if ( IoControlCode == 0x22EC00 )
{
char enc_key[32];
memset(enc_key, 0, sizeof(enc_key));
memmove(enc_key, "C110DD4FE9434147B92A5A1E3FDBF29A", 32ui64);
memcpy(enc_key + 13, ioctl_args->key, 16);
size_t cb_decrypted = 0;
my_decrypted_cmd* decryptedCmd = NULL;
DWORD iv_size = ioctl_args->iv_size;
DWORD input_size = *(DWORD*)(ioctl_args + bufferLen - 6);
// really just calls BCrypt API to get an AES implementation
if ( (unsigned int)decrypt_ioctl_params(enc_key, 32, ioctl_args->iv, iv_size, ioctl_args + bufferLen - input_size - 6, input_size, &decryptedCmd, &cb_decrypted) )
{
// Decryption failed
if ( decryptedCmd )
ExFreePoolWithTag(decryptedCmd, 0);
irp->IoStatus.Status = 0xC000000D;
goto Fail_Out;
}
IoControlCode = decryptedCmd->opcode;
Rweverything_Args = &decryptedCmd->args;
}
else // not 0x22EC00
{
if ( IoControlCode != 0x22E858 &&
IoControlCode != 0x22E860 &&
IoControlCode != 0x22E800 &&
IoControlCode != 0x22E804 )// whitelisted control codes
IoControlCode = 0; // block everything else
}
ड्राइवर कुछ उबाऊ ऑपरेशनों की अनुमति देता है जो कुछ PMIO करते हैं, लेकिन सभी "मज़ेदार" नियंत्रण कोड इस डिक्रिप्शन रूटीन के पीछे बंद हैं। इस स्पष्ट अनुमति-सूची के बावजूद, इसमें अभी भी सभी खतरनाक Rweverything कार्यक्षमताएँ शामिल हैं। इन खतरनाक सुविधाओं को छिपाने के बजाय, शायद उन्हें पूरी तरह से हटा दिया जाना चाहिए था।
इसके अलावा, दिलचस्प बात यह है कि यह उपयोगकर्ता को कुंजी का कुछ हिस्सा निर्दिष्ट करने की भी अनुमति देता है (???), किस कारण से मुझे कोई विचार नहीं है। कोड बहुत खराब लिखा गया है।
वैसे भी, इस अजीब एन्क्रिप्टेड API का उपयोग करने और इसे अपनी पसंद के अनुसार मनमाना ioctl कॉल पास करने के लिए क्लाइंट कोड लिखना अपेक्षाकृत आसान है। मैं आपको उसके विवरण से बोर नहीं करूंगा।
हम ड्राइवर के लिए एक हैंडल खोलते हैं और ioctl को कॉल करने के लिए DeviceIoControl का उपयोग करते हैं, यह बहुत मानक सामान है।
HANDLE hDevice = CreateFileA("\\\\.\\GlobalRoot\\Device\\AsrDrv104", GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// ... set up the encrypted ioctl data
BOOL result = DeviceIoControl(hDevice, 0x22EC00, ioctl_data, in_buf_size, out_buf, sizeof(out_buf), &bytes_returned, NULL);
अब जब हम ड्राइवर के छिपे हुए Rweverything भाग से बात करने में सक्षम हैं, तो पहली चीज़ जो मैं करना चाहता था वह एक क्रैश ट्रिगर करना था ताकि मुझे पता चले कि मेरा ड्राइवर क्लाइंट काम कर रहा है।
इसे प्राप्त करने का सबसे सीधा तरीका CR3 को कबाड़ से ओवरराइट करना है। मुझे पता है कि आप में से कुछ पढ़ने वाले नौसिखिए हैं और यह ठीक है, इसलिए मैं विस्तार से समझाऊंगा। मैं भी बेवकूफ हूँ, इसलिए शायद इससे आपको सीखने में मदद मिलेगी। यदि आप जानते हैं कि आप क्या कर रहे हैं, तो आप इसे छोड़ सकते हैं।
x86 पर, जब पेजिंग सक्षम होती है (आधुनिक ऑपरेटिंग सिस्टम में लगभग हर समय), CR3 शीर्ष स्तर के पेज टेबल डायरेक्ट्री के भौतिक आधार पते की ओर इशारा करता है। यदि आप नहीं जानते कि इसका क्या अर्थ है, तो वर्चुअल मेमोरी के लिए Wikipedia लेख पढ़ें।