
iOS kernelcaches के विश्लेषण के लिए एक IDA टूलकिट।
ida_kernelcache IDA Pro के लिए एक IDAPython मॉड्यूल है जो iOS कर्नेलकैश के साथ काम करना आसान बनाता है। यह मॉड्यूल निम्नलिखित कार्य प्रदान करता है:
__PRELINK_INFO सेगमेंट को पायथन डिक्शनरी में पार्स करना।__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 स्क्रिप्ट चुनें। यह IDAPython इंटरप्रेटर में ida_kernelcache और kc नामों के तहत ida_kernelcache मॉड्यूल लोड करेगा। 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 एक संरचना प्रकार को पायथन डिक्शनरी या पायथन एक्सेसर ऑब्जेक्ट में पढ़ता है, जो डेटा संरचनाओं को पार्स करना बहुत आसान बनाता है। 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++ क्लास पुनर्निर्माण है, जो कर्नेलकैश में पाए जाने वाले क्लास का प्रतिनिधित्व करने वाले IDA स्ट्रक्ट बनाने के लिए OSMetaClass जानकारी और डेटा प्रवाह विश्लेषण का उपयोग करेगा। ये प्रतिनिधित्व स्यूडोकोड प्रतिनिधित्व की पठनीयता में नाटकीय रूप से सुधार कर सकते हैं। अधिक जानने के लिए, पोस्ट देखें 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 के बीच अंतर करना संभव हो जाता है। यह मॉड्यूल निर्दिष्ट पता वाले kext को निर्धारित करने के लिए kernelcache_kext फ़ंक्शन (शीर्ष स्तर पर पुनः निर्यात) भी प्रदान करता है (केवल पुराने iOS 11 स्प्लिट-केक्सट कर्नेलकैश प्रारूप पर)।
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 कहा जाना चाहिए। इस तकनीक का उपयोग अधिकांश क्लास में अधिकांश वर्चुअल मेथड को प्रतीकित करने के लिए किया जा सकता है।