
iOS kernelcaches का विश्लेषण करने के लिए एक IDA टूलकिट।
यह फ़ोर्क IDA 9.x / Python 3 / iOS 27.0 beta 1 पर काम करने के लिए अपडेट किया गया था
ida_kernelcache, IDA Pro के लिए एक IDAPython मॉड्यूल है जो iOS कर्नेलकैश के साथ काम करना आसान बनाता है। मॉड्यूल निम्नलिखित कार्य प्रदान करता है:
__PRELINK_INFO सेगमेंट को Python डिक्शनरी में पार्स करें।__got सेक्शन में ऑफ़सेट और __stubs सेक्शन में स्टब फ़ंक्शंस को सिंबलिकेट करें।मुख्य प्रोसेसिंग फ़ंक्शन को किसी भी मैन्युअल विश्लेषण या रिवर्स इंजीनियरिंग से पहले चलाने के लिए डिज़ाइन किया गया है। डिफ़ॉल्ट सेटिंग्स के साथ, IDA कर्नेलकैश में बहुत सारी उपयोगी जानकारी को मिस कर देता है। ये स्क्रिप्ट्स कर्नेलकैश की ज्ञात संरचना का लाभ उठाकर उपयोगी जानकारी को स्वचालित रूप से प्रसारित करने में IDA की मदद करती हैं।
मॉड्यूल में मौजूद मानक कार्यक्षमता के अलावा, ida_kernelcache में iOS कर्नेलकैश का विश्लेषण करना आसान बनाने के लिए कई स्क्रिप्ट्स शामिल हैं। उदाहरण के लिए, आप किसी फ़ंक्शन द्वारा उपयोग किए जाने वाले C स्ट्रक्ट्स को स्वचालित रूप से उत्पन्न करने के लिए स्क्रिप्ट्स का उपयोग कर सकते हैं।
ida_kernelcache में उपयोग की जाने वाली कई तकनीकें memctl के लिए विकसित की गई थीं और सीधे उससे उधार ली गई हैं।
ida_kernelcache का परीक्षण IDA Pro 6.95 के साथ iOS संस्करणों 10.1.1, 11.0, 11.2, 11.3.1 और 12.0 बीटा के कर्नेलकैश पर किया गया है। वर्तमान में केवल iOS 10 और उसके बाद के Arm64 कर्नेलकैश समर्थित हैं।
आपके पास पहले से ही IDA में एक डीकंप्रेस्ड कर्नेलकैश फ़ाइल लोड होनी चाहिए। आप ऑनलाइन Apple से किसी विशेष IPSW को डाउनलोड करने का URL पा सकते हैं, और कर्नेलकैश को डीकंप्रेस करने में सक्षम कई सार्वजनिक उपकरण (memctl सहित) मौजूद हैं।
IDA में, मेन्यू बार से "File" -> "Script file..." चुनें, फिर मुख्य निर्देशिका में ida_kernelcache.py स्क्रिप्ट चुनें। यह ida_kernelcache मॉड्यूल को IDAPython इंटरप्रेटर में ida_kernelcache और kc नामों से लोड करेगा। IDAPython प्रॉम्प्ट पर, kc.kernelcache_process() टाइप करें और कर्नेलकैश का विश्लेषण शुरू करने के लिए Enter दबाएं। यह फ़ंक्शन ida_kernelcache द्वारा समर्थित सभी प्रमुख विश्लेषण करता है। फ़ंक्शन कई मिनट तक चलेगा क्योंकि IDA नए फ़ंक्शंस की पहचान और विश्लेषण करता है।
ida_kernelcache पतों के लिए उपयोगकर्ता नामों को अधिलेखित न करने का प्रयास करेगा। इसका मतलब है कि यदि kernelcache_process के साथ आरंभीकरण से पहले कर्नेलकैश का मैन्युअल रूप से विश्लेषण किया गया है, तो परिणाम उतने गहन नहीं हो सकते क्योंकि उपयोगकर्ता-निर्दिष्ट नाम स्वचालित नाम प्रसार को अवरुद्ध कर सकते हैं। हालांकि, इसकी भी कोई गारंटी नहीं है कि ida_kernelcache पिछले विश्लेषण को खराब नहीं करेगा, इसलिए यदि आप पहले से विश्लेषण की गई कर्नेलकैश फ़ाइल पर kernelcache_process चलाने का निर्णय लेते हैं, तो पहले बैकअप बना लें।
ida_kernelcache को ida_kernelcache.py के माध्यम से लोड करने का इरादा है; ida_kernelcache निर्देशिका में उपमॉड्यूल को सीधे लोड करने का इरादा नहीं है। हालांकि, ida_kernelcache इनमें से कई उपमॉड्यूल की कार्यक्षमता को उजागर करता है। यहाँ बताया गया है कि उनमें से प्रत्येक क्या करता है:
ida_utilities:
यह मॉड्यूल IDA के कुछ फ़ंक्शंस को लपेटता है ताकि उपयोग में आसान API प्रदान किया जा सके। विशेष रूप से उपयोगी हैं is_mapped, read_word, read_struct, force_function, और ReadWords। is_mapped जाँचता है कि कोई पता मैप किया गया है या नहीं, और वैकल्पिक रूप से इसमें कोई ज्ञात मान है या नहीं। read_word किसी पते से एक चर-आकार का शब्द पढ़ता है। read_struct एक संरचना प्रकार को Python डिक्शनरी या Python एक्सेसर ऑब्जेक्ट में पढ़ता है, जो डेटा संरचनाओं को पार्स करना बहुत आसान बनाता है। force_function किसी पते को IDA में किसी फ़ंक्शन की शुरुआत में बदलने के लिए कई तरकीबें आज़माता है। ReadWords एक जनरेटर है जो एक श्रेणी में डेटा शब्दों और उनके पतों पर पुनरावृति करता है।
build_struct: इस आंतरिक मॉड्यूल में संरचना पर एक्सेस के अनुक्रम के आधार पर स्वचालित रूप से IDA संरचना को पॉप्युलेट करने के लिए उपयोगिताएँ हैं।
class_struct:
यह मॉड्यूल C++ वर्चुअल मेथड टेबल्स और क्लासेस का प्रतिनिधित्व करने वाली IDA संरचनाएँ उत्पन्न करने के लिए फ़ंक्शन प्रदान करता है। initialize_vtable_structs (सिंबलिकेटेड) वर्चुअल मेथड टेबल्स को स्कैन करता है और वर्चुअल मेथड पॉइंटर्स को होल्ड करने के लिए IDA संरचनाएँ बनाता है। प्रत्येक क्लास के फ़ील्ड तक पहुँच की पहचान करने के लिए वर्चुअल मेथड्स पर डेटा प्रवाह विश्लेषण करता है, फिर क्लासेस का प्रतिनिधित्व करने के लिए IDA संरचनाएँ बनाता है। वे निर्देश जो किसी फ़ील्ड को संदर्भित करते प्रतीत होते हैं, उन्हें संरचना ऑफ़सेट संदर्भों में भी बदल दिया जाता है। अधिक विवरण के लिए मॉड्यूल डॉकस्ट्रिंग देखें।
ida_kernelcache_reload.py स्क्रिप्ट ida_kernelcache.py के समान है, सिवाय इसके कि यह ida_kernelcache मॉड्यूल और सभी उपमॉड्यूल को पुनः लोड करने के लिए मजबूर करती है। यह अधिकांशतः विकास के लिए उपयोगी है।
scripts निर्देशिका में ऐसी स्क्रिप्ट्स हैं जो किसी प्रकार का विश्लेषण करने के लिए ida_kernelcache का उपयोग करती हैं। ये स्क्रिप्ट्स मुख्य ida_kernelcache मॉड्यूल का हिस्सा होने के लिए बहुत विशिष्ट हैं, लेकिन कर्नेलकैश को रिवर्स इंजीनियर करते समय ये उपयोगी होती हैं। इनमें शामिल हैं:
find_virtual_method_overrides.py: एक स्क्रिप्ट जो किसी क्लास के वंशजों को खोजने के लिए है जो निर्दिष्ट स्ट्रिंग वाले वर्चुअल मेथड को ओवरराइड करते हैं। मिलान किए गए ओवरराइड कंसोल पर मुद्रित होते हैं।
populate_struct.py: वर्तमान पते से शुरू करके डेटा प्रवाह विश्लेषण करके C++ क्लास या C स्ट्रक्ट के लिए फ़ील्ड पॉप्युलेट करें।
process_external_methods.py:
फ़ज़िंग टूल्स द्वारा उपयोग के लिए एक IOExternalMethod या IOExternalMethodDispatch सरणी को मानक रूप में संसाधित करें।
यदि आप Hex-Rays डीकंपाइलर का उपयोग कर रहे हैं, तो ida_kernelcache की अधिक दिलचस्प विशेषताओं में से एक स्वचालित C++ क्लास पुनर्निर्माण है, जो कर्नेलकैश में पाए जाने वाले क्लासेस का प्रतिनिधित्व करने के लिए OSMetaClass जानकारी और डेटा प्रवाह विश्लेषण का उपयोग करके IDA संरचनाएँ बनाएगी। ये निरूपण स्यूडोकोड निरूपण की पठनीयता में नाटकीय रूप से सुधार कर सकते हैं। अधिक जानने के लिए, पोस्ट देखें Reconstructing C++ classes in the iOS kernelcache using IDA Pro।
iOS 12 के साथ, Apple ने कुछ उपकरणों पर एक नया कर्नेलकैश प्रारूप पेश किया। बदलावों के बीच, इस नए कर्नेलकैश के कर्नेल पॉइंटर्स को उन्हें एक सूची में जोड़ने के लिए टैग किया गया है, संभवतः iBoot को प्रीलिंक डिक्शनरी में _PrelinkLinkKASLROffsets डेटा के बिना कर्नेल को स्लाइड करने की अनुमति देने के लिए। इस प्रारूप का उपयोग करके IDA में स्टॉक कर्नेलकैश का विश्लेषण करने का प्रयास करना लापता क्रॉस-रेफरेंस के कारण कठिन है। विवरण के लिए लेख देखें Analyzing the iOS 12 kernelcache's tagged pointers।
यदि आप बिना किसी अतिरिक्त प्रसंस्करण के केवल कर्नेलकैश में पॉइंटर्स को अनटैग करना चाहते हैं, तो kc.tagged_pointers.untag_pointers() चलाएँ।
इनमें से कुछ कार्यक्षमता संभवतः केवल Apple कर्नेलकैश से अधिक व्यापक रूप से लागू होती है (उदाहरण के लिए, vtable विश्लेषण और प्रतीक प्रसार, या ida_utilities.py में अधिकांश फ़ंक्शन)। फिर भी, मैंने आयात दायरे को केवल ida_kernelcache मॉड्यूल तक सीमित रखा है क्योंकि मैंने अन्य प्रकार की बाइनरी पर इनमें से किसी का परीक्षण नहीं किया है।
ida_kernelcache MIT लाइसेंस के तहत जारी किया गया है।
ida_kernelcache में अधिकांश कार्यक्षमता memctl से उधार ली गई है, जो MIT लाइसेंस के तहत भी जारी किया गया है। अन्य स्रोतों को संबंधित फ़ाइलों में टिप्पणियों में नोट किया गया है।
Brandon Azad
initialize_class_structsclasses:
यह मॉड्यूल ClassInfo प्रकार को परिभाषित करता है जो कर्नेलकैश में C++ क्लासेस के बारे में जानकारी रखता है और कर्नेलकैश को स्कैन करके क्लासेस का पता लगाने और क्लास नामों से ClassInfo ऑब्जेक्ट्स के मानचित्रण के साथ वैश्विक class_info शब्दकोश को पॉप्युलेट करने के लिए collect_class_info फ़ंक्शन प्रदान करता है। ClassInfo प्रकार प्रत्येक C++ क्लास के लिए क्लास का नाम, OSMetaClass इंस्टेंस, वर्चुअल मेथड टेबल और सुपरक्लास का नाम रिकॉर्ड करता है। इसके अतिरिक्त, प्रत्येक ClassInfo ऑब्जेक्ट सुपरक्लास के ClassInfo और सभी प्रत्यक्ष उपवर्गों के ClassInfo के संदर्भों को संग्रहीत करता है, जिससे क्लास पदानुक्रम की जाँच करना और उसे पार करना आसान हो जाता है। collect_class_info वैश्विक vtables सेट में सभी वर्चुअल मेथड टेबल्स का सेट भी संग्रहीत करता है।
data_flow: इस आंतरिक मॉड्यूल में डेटा प्रवाह संचालन शामिल हैं जिनका उपयोग ida_kernelcache के शेष भाग द्वारा किया जाता है।
kernel:
यह मॉड्यूल base और prelink_info वैश्विक चर प्रदान करता है। base कर्नेल इमेज का आधार पता है (कर्नेल के Mach-O हेडर की शुरुआत)। prelink_info पार्स किया गया __PRELINK_INFO शब्दकोश है।
kplist:
यह मॉड्यूल कर्नेल-शैली plist को पार्स करने के लिए kplist_parse फ़ंक्शन प्रदान करता है।
metaclass:
यह मॉड्यूल initialize_metaclass_symbols फ़ंक्शन प्रदान करता है जो प्रत्येक ज्ञात OSMetaClass इंस्टेंस के लिए एक प्रतीक जोड़ता है।
offset:
यह मॉड्यूल initialize_data_offsets और initialize_offset_symbols फ़ंक्शन प्रदान करता है। पहला उन पॉइंटर्स की तलाश में सेगमेंट को स्कैन करता है जिन्हें ऑफ़सेट में परिवर्तित किया जा सकता है। दूसरा प्रत्येक kext के __got सेक्शन में ऑफ़सेट को सिंबलिकेट करता है यदि ऑफ़सेट के लक्ष्य में कोई प्रतीक है।
segment:
यह मॉड्यूल IDA के सेगमेंट को अधिक उपयोगी बनाने के लिए उनका नाम बदलने के लिए initialize_segments फ़ंक्शन प्रदान करता है। डिफ़ॉल्ट रूप से, IDA बंडल पहचानकर्ता के अनुमान को क्षेत्र का वर्णन करने वाले Mach-O सेक्शन के साथ जोड़कर सेगमेंट नाम बनाता प्रतीत होता है। initialize_segments __PRELINK_INFO शब्दकोश से वास्तविक बंडल पहचानकर्ता निकालता है और प्रत्येक सेगमेंट का नाम बदलकर उसमें बंडल पहचानकर्ता, Mach-O सेगमेंट और Mach-O सेक्शन शामिल करता है। इससे, उदाहरण के लिए, __TEXT.__const और __DATA_CONST.__const के बीच अंतर करना संभव हो जाता है। यह मॉड्यूल kernelcache_kext फ़ंक्शन (शीर्ष स्तर पर पुनः निर्यात) भी प्रदान करता है ताकि निर्दिष्ट पते वाले kext का निर्धारण किया जा सके (केवल पुराने iOS 11 स्प्लिट-kext कर्नेलकैश प्रारूप पर)।
stub:
कर्नेलकैश में कई kext में __stubs सेक्शन में स्टब फ़ंक्शंस होते हैं जो कर्नेल में फ़ंक्शंस पर जाते हैं। दुर्भाग्य से, ये स्टब क्रॉस-रेफरेंस और प्रकार की जानकारी के प्रसार में बाधा उत्पन्न करते हैं। यह मॉड्यूल इन समस्याओं को हल नहीं करता है, लेकिन स्टब फ़ंक्शंस का स्वचालित रूप से नाम बदलकर स्टब को देखना थोड़ा आसान बना देता है ताकि लक्ष्य फ़ंक्शन का नाम दिखाई दे। स्टब और उनके लक्ष्यों को IDA में जबरन फ़ंक्शंस में बदल दिया जाता है, जो मूल स्रोत कोड में फ़ंक्शंस के साथ IDA में फ़ंक्शंस को संरेखित करने में मदद करता है।
tagged_pointers: नए iOS 12 मर्ज किए गए कर्नेलकैश प्रारूप में प्रत्येक पॉइंटर के ऊपरी 2 बाइट्स को एक ऑफ़सेट के साथ टैग किया जाता है ताकि पॉइंटर्स को एक सूची में एक साथ जोड़ा जा सके। इस मॉड्यूल में उन टैग किए गए पॉइंटर्स को संसाधित और पुनर्स्थापित करने के लिए फ़ंक्शन शामिल हैं।
vtable:
यह मॉड्यूल वर्चुअल मेथड टेबल्स के साथ काम करने के लिए कई उपयोगी फ़ंक्शन प्रदान करता है, जिनमें vtable_length, convert_vtable_to_offsets, vtable_overrides, initialize_vtable_symbols, और initialize_vtable_method_symbols शामिल हैं। vtable_length जाँचता है कि निर्दिष्ट पता vtable हो सकता है या नहीं और vtable की लंबाई लौटाता है। जनरेटर vtable_overrides एक क्लास में वर्चुअल मेथड्स को गिनता है जो सुपरक्लास द्वारा उपयोग किए जाने वाले वर्चुअल मेथड्स को ओवरराइड करते हैं। फ़ंक्शन initialize_vtable_symbols प्रत्येक पहचाने गए vtable की शुरुआत के लिए एक प्रतीक जोड़ता है। initialize_vtable_method_symbols प्रत्येक vtable में ओवरराइड किए गए मेथड्स के माध्यम से पुनरावृति करता है और सुपरक्लास से उपवर्ग में प्रतीकों का प्रसार करता है। यह संभव है क्योंकि IOKit में अधिकांश बेस क्लासेस XNU में अपेक्षाकृत पूर्ण प्रतीक जानकारी के साथ परिभाषित हैं। उपवर्ग के vtable में प्रत्येक मेथड ओवरराइड को सुपरक्लास में मेथड के समान इंटरफ़ेस का पालन करना चाहिए, जिसका अर्थ है कि हम सुपरक्लास में वर्चुअल मेथड प्रतीक में सुपरक्लास के नाम के स्थान पर उपवर्ग का नाम प्रतिस्थापित करके ओवरराइड के लिए एक प्रतीक उत्पन्न कर सकते हैं। उदाहरण के लिए, यदि हमारे पास AppleKeyStore क्लास में इंडेक्स 7 पर वर्चुअल मेथड के लिए कोई नाम नहीं है, लेकिन हम जानते हैं कि इसके सुपरक्लास IOService में इंडेक्स 7 पर वर्चुअल मेथड को __ZNK9IOService12getMetaClassEv कहा जाता है, तो हम अनुमान लगा सकते हैं कि इंडेक्स 7 को उपवर्ग में __ZNK13AppleKeyStore12getMetaClassEv कहा जाना चाहिए। इस तकनीक का उपयोग अधिकांश क्लासेस में अधिकांश वर्चुअल मेथड्स को सिंबलिकेट करने के लिए किया जा सकता है।