
Un toolkit IDA per analizzare i kernelcache iOS.
ida_kernelcache è un modulo IDAPython per IDA Pro che facilita il lavoro con i kernelcache iOS. Il modulo fornisce funzioni per:
__PRELINK_INFO del kernel in un dizionario Python.__got e le funzioni stub nelle sezioni __stubs.La funzione di elaborazione principale è progettata per essere eseguita prima di qualsiasi analisi manuale o reverse engineering. Con le impostazioni predefinite, IDA tende a perdere molte informazioni utili nel kernelcache. Questi script aiutano IDA sfruttando la struttura nota del kernelcache per propagare automaticamente informazioni utili.
Oltre alle funzionalità standard del modulo, ida_kernelcache contiene diversi script per facilitare l'analisi del kernelcache iOS. Ad esempio, puoi utilizzare gli script per generare automaticamente struct C utilizzate da una funzione.
Molte delle tecniche utilizzate in ida_kernelcache sono state sviluppate per e prese direttamente da memctl.
ida_kernelcache è stato testato con IDA Pro 6.95 su kernelcache per le versioni iOS 10.1.1, 11.0, 11.2, 11.3.1 e 12.0 beta. Attualmente sono supportati solo kernelcache Arm64 da iOS 10 in poi.
Devi già avere un file kernelcache decompresso caricato in IDA. Puoi trovare l'URL per scaricare un IPSW specifico da Apple online, e ci sono diversi strumenti pubblici (incluso memctl) in grado di decomprimere il kernelcache.
In IDA, seleziona "File" -> "Script file..." dalla barra dei menu, quindi scegli lo script ida_kernelcache.py nella directory principale. Questo caricherà il modulo ida_kernelcache nell'interprete IDAPython con i nomi ida_kernelcache e kc. Nel prompt IDAPython, digita kc.kernelcache_process() e premi Invio per iniziare l'analisi del kernelcache. Questa funzione esegue tutte le principali analisi supportate da ida_kernelcache. La funzione verrà eseguita per diversi minuti mentre IDA identifica e analizza nuove funzioni.
ida_kernelcache cercherà di non sovrascrivere i nomi utente per gli indirizzi. Ciò significa che se il kernelcache è stato analizzato manualmente prima dell'inizializzazione con kernelcache_process, i risultati potrebbero non essere così completi perché i nomi specificati dall'utente potrebbero bloccare la propagazione automatica dei nomi. Tuttavia, non c'è nemmeno la garanzia che ida_kernelcache non rovini l'analisi precedente, quindi se decidi di eseguire kernelcache_process su un file kernelcache che hai già analizzato, fai prima un backup.
ida_kernelcache è pensato per essere caricato tramite ida_kernelcache.py; i sottomoduli nella directory ida_kernelcache non devono essere caricati direttamente. Tuttavia, ida_kernelcache espone le funzionalità di molti di questi sottomoduli. Ecco cosa fa ciascuno di essi:
ida_utilities:
Questo modulo incapsula alcune funzioni di IDA per fornire un'API più facile da usare. Particolarmente utili sono is_mapped, read_word, read_struct, force_function e ReadWords. is_mapped controlla se un indirizzo è mappato e, opzionalmente, se contiene un valore noto. read_word legge una parola di dimensione variabile da un indirizzo. read_struct legge un tipo struct in un dizionario Python o in un oggetto accessor Python, il che rende molto più semplice l'analisi delle strutture dati. force_function prova diversi trucchi per convertire un indirizzo nell'inizio di una funzione in IDA. ReadWords è un generatore per iterare su parole di dati e i loro indirizzi in un intervallo.
build_struct: Questo modulo interno contiene utility per popolare automaticamente una struct IDA basandosi su una sequenza di accessi alla struct.
class_struct:
Questo modulo fornisce funzioni per generare struct IDA che rappresentano le tabelle dei metodi virtuali C++ e le classi. initialize_vtable_structs esamina le tabelle dei metodi virtuali (simbolizzate) e crea struct IDA per contenere i puntatori ai metodi virtuali. initialize_class_structs esegue un'analisi del flusso di dati sui metodi virtuali per identificare gli accessi ai campi di ogni classe, quindi costruisce struct IDA per rappresentare le classi. Le istruzioni che sembrano fare riferimento a un campo vengono anche convertite in riferimenti a offset di struct. Vedi la docstring del modulo per maggiori dettagli.
classes:
Questo modulo definisce il tipo ClassInfo che contiene informazioni sulle classi C++ nel kernelcache e fornisce la funzione collect_class_info per esaminare il kernelcache alla ricerca di classi e popolare il dizionario globale class_info con una mappa dai nomi delle classi agli oggetti ClassInfo. Il tipo ClassInfo registra il nome della classe, l'istanza OSMetaClass, la tabella dei metodi virtuali e il nome della superclasse per ogni classe C++. Inoltre, ogni oggetto ClassInfo memorizza riferimenti al ClassInfo della superclasse e al ClassInfo di tutte le sottoclassi dirette, facilitando l'esame e la navigazione della gerarchia delle classi. collect_class_info memorizza anche l'insieme di tutte le tabelle dei metodi virtuali nell'insieme globale vtables.
data_flow: Questo modulo interno contiene operazioni di flusso di dati utilizzate dal resto di ida_kernelcache.
kernel:
Questo modulo fornisce le variabili globali base e prelink_info. base è l'indirizzo base dell'immagine del kernel (l'inizio dell'intestazione Mach-O del kernel). prelink_info è il dizionario __PRELINK_INFO analizzato.
kplist:
Questo modulo fornisce la funzione kplist_parse per analizzare plist in stile kernel.
metaclass:
Questo modulo fornisce la funzione initialize_metaclass_symbols che aggiunge un simbolo per ogni istanza OSMetaClass conosciuta.
offset:
Questo modulo fornisce le funzioni initialize_data_offsets e initialize_offset_symbols. La prima esamina i segmenti alla ricerca di puntatori che possono essere convertiti in offset. La seconda simbolizza gli offset nella sezione __got di ogni kext se la destinazione dell'offset ha un simbolo.
segment:
Questo modulo fornisce la funzione initialize_segments per rinominare i segmenti di IDA in modo che siano più utili. Per impostazione predefinita, IDA sembra creare i nomi dei segmenti combinando un'ipotesi dell'identificatore del bundle con la sezione Mach-O che descrive la regione. initialize_segments estrae il vero identificatore del bundle dal dizionario __PRELINK_INFO e rinomina ogni segmento includendo l'identificatore del bundle, il segmento Mach-O e la sezione Mach-O. Ciò rende possibile, ad esempio, distinguere tra __TEXT.__const e __DATA_CONST.__const. Questo modulo fornisce anche la funzione kernelcache_kext (riesportata al livello superiore) per determinare il kext che contiene l'indirizzo specificato (solo nel vecchio formato kernelcache split-kext di iOS 11).