
CVE-2022-32932 एक और कमज़ोरी है जो मैंने ANE कर्नेल इंटरफ़ेस में खोजी; यह एक डबल फ़ेच समस्या है जिसके परिणामस्वरूप एक दिलचस्प OOB write हुआ।
H11ANEIn::patchMutableSurface() (H11ANEIn::ANE_ProgramSendRequest_gated से प्राप्त) तब कॉल किया जाता है यदि model.hwx में एक म्यूटेबल प्रक्रिया हो और साथ ही initInfo सेक्शन भी हो। मैंने ऐसा मॉडल खोजा लेकिन कोई नहीं मिला, इसलिए मैंने एक प्री-कंपाइल्ड मॉडल को पैच कर दिया और उसे लोड करने के लिए CVE-2022-32845 का उपयोग किया। कृपया ध्यान रखें कि डिफ़ॉल्ट ऐप सैंडबॉक्स से कमज़ोर कोड पथ तक पहुँचने के लिए CVE-2022-32845 आवश्यक नहीं है, समान परिणाम पाने के लिए एक कस्टम mlmodel संकलित करना पर्याप्त है। CVE-2022-32845 के बारे में अधिक विवरण आप मेरी presentation slides में पा सकते हैं।
ZinComputeProgramUpdateMutables() एक और फ़ंक्शन है जिसे H11ANEIn::patchMutableSurface() द्वारा कॉल किया जाता है, और फ़ंक्शन प्रोटोटाइप निम्नलिखित है:
ZinComputeProgramStatus __cdecl ZinComputeProgramUpdateMutables(
uint64_t procedureId,
const ZinComputeProgramInitInfo *init_info,
const ANECMutableProcedureInfo *mutable_procedure_info,
uint64_t mut_procedure_info_size,
void *MUTK_kernel_section,
uint64_t MUTK_kernel_section_size);
init_info: initInfo सेक्शन है जिसमें एक क्रमबद्ध इनपुट होता है, आप serializer फ़ंक्शन serialize_initinfo_section() को weightBufs एक्सप्लॉइट सोर्स कोड में पा सकते हैं। mutable_procedure_info : हमलावर द्वारा प्रदान किया गया एक साझा IOSurface बफर है, इसे weightBufs एक्सप्लॉइट में weightsBuffer भी कहा जाता है। mut_procedure_info_size: यह mutable_procedure_info सरफेस बफर के आकार को दर्शाता है। MUTK_kernel_section: (या MUTK) यह एक IOSurface ऑब्जेक्ट का मैपिंग बफर है जो कर्नेल द्वारा प्रोग्राम लोडिंग चरण के दौरान बनाया जाता है। MUTK_kernel_section_size: म्यूटेबल कर्नेल सेक्शन का आकार है।

लूप 88-92 mutable_procedure_info ऑब्जेक्ट के भीतर MutableWeight ऑब्जेक्ट की संख्या की गणना करता है, फिर 93 पर MutableWeight ऐरे के आवंटन आकार की गणना करता है। उसके बाद, ANECMutableWeight ऑब्जेक्ट्स की ऐरे 100 पर आवंटित की जाती है, फिर लूप 111-127 में ANECGetMutableWeight() द्वारा उपयुक्त वेट बफर/साइज़ जोड़ी से भर दी जाती है।
ANECGetMutableOperationInfo() हमारी साझा मेमोरी से एक opsInfo ऑब्जेक्ट लौटाता है:
opsInfo *__fastcall ANECGetMutableOperationInfo(const ANECMutableProcedureInfo *MutableProcedureInfo, unsigned int id)
{
unsigned int weight_buffer_size; // w8
opsInfo *opInfo; // x0
weight_buffer_size = MutableProcedureInfo->header.weight_buffer_size;
if ( !weight_buffer_size )
return 0LL;
opInfo = (opsInfo *)((char *)MutableProcedureInfo + MutableProcedureInfo->wb_offsets[id]);
while ( opInfo->op_index != id )
{
if ( !--weight_buffer_size )
return 0LL;
}
return opInfo;
}
ANECGetMutableWeight का स्यूडो-कोड निम्नलिखित है:
void __fastcall ANECGetMutableWeight(
const ANECMutableProcedureInfo *procedure_info,
weightInfo *a2,
ANECMutableWeight *a3)
{
uint64_t wi_size; // x9
wi_size = a2->wi_size;
a3->_weightBuf = (char *)procedure_info + a2->wi_off;
a3->_weightBufSize = wi_size;
}
ANECGetMutableWeightInfo का स्यूडो-कोड निम्नलिखित है:
weightInfo *__fastcall ANECGetMutableWeightInfo(
const ANECMutableProcedureInfo *MutableProcedureInfo,
opsInfo *a2,
unsigned int a3)
{
if ( a2->op_count <= a3 )
return 0LL;
else
return (weightInfo *)((char *)MutableProcedureInfo + a2->op_offsets[a3]);
}
मैंने ANECMutableProcedureInfo का प्रारूप “Attacking Apple’s Neural Engine” स्लाइड्स में पहले ही वर्णित कर दिया है, इसलिए यदि आपने अभी तक नहीं पढ़ा है तो बेझिझक इसे पढ़ें। संरचना की परिभाषा weightBufs एक्सप्लॉइट में ' aneProgram.h' पर पाई जा सकती है।
यदि आपने ध्यान दिया हो, ANECGetMutableOperationInfo()->op_count को दो बार प्राप्त किया जाता है: एक बार ANECMutableWeight ऐरे को आवंटित करने के लिए आकार की गणना करने हेतु, और एक बार इस ऐरे को भरने के लिए।
चूँकि mutable_procedure_info बफर एक साझा मेमोरी है, एक हमलावर पहले और दूसरे उपयोग के बीच opsInfo->op_count का मान बदलने के लिए एक अलग थ्रेड का उपयोग कर सकता है, जिसके परिणामस्वरूप आकार में बेमेल होगा और यह kalloc var zone, kheap defaul या कर्नेल मैप में एक दिलचस्प OOB write की ओर ले जाएगा।
इस कमज़ोरी का उपयोग कई दिलचस्प तरीकों से किया जा सकता है। उदाहरण के लिए, एक हमलावर लाइन 93 पर total_count = 0x1000; सेट कर सकता है, फिर opsInfo->count को कुछ बड़ा बढ़ा सकता है, जिससे ANECGetMutableWeight() में डेटा आउट-ऑफ-बाउंड्स कॉपी हो सकता है।
यदि OOB write किसी अनमैप्ड मेमोरी क्षेत्र तक पहुँच गया है तो कर्नेल नीचे दिखाए गए निर्देश पर पैनिक करेगा:
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D08 EXPORT _ANECGetMutableWeight
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D08 _ANECGetMutableWeight ; CODE XREF: _ZinComputeProgramUpdateMutables+270↓p
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D08 LDP X8, X9, [X1,#8]
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D0C ADD X8, X0, X8
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D10 STP X8, X9, [X2] // <---- Kernel panic
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D14 RET
यह बग एक मजबूत प्रिमिटिव प्रदान करता है, जिसमें यह दो 64-बिट मान लिखता है: एक कर्नेल एड्रेस जो हमारे यूज़र साझा बफर की ओर इंगित करता है और एक (अर्ध-)मनमाना 64-बिट मान।
प्रूफ-ऑफ-कॉन्सेप्ट को पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है। हालाँकि, weightBufs एक्सप्लॉइट में कमज़ोर कोड पथ तक पहुँचने के लिए आवश्यक सब कुछ शामिल है। शुभकामनाएँ :-)।