
Un toolkit IDA per analizzare i kernelcache iOS.
Questo fork è stato aggiornato per funzionare con IDA 9.x / Python 3 / iOS 27.0 beta 1
ida_kernelcache è un modulo IDAPython per IDA Pro che semplifica il lavoro con i kernelcache iOS. Il modulo fornisce funzioni per:
__PRELINK_INFO del kernel in un dizionario Python.__got e delle 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 le informazioni utili.
Oltre alle funzionalità standard del modulo, ida_kernelcache contiene diversi script per semplificare l'analisi del kernelcache iOS. Ad esempio, è possibile utilizzare gli script per autogenerare struct C usate da una funzione.
Molte delle tecniche usate in ida_kernelcache sono state sviluppate per memctl e prese direttamente in prestito da esso.
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.
È necessario avere già un file kernelcache decompresso caricato in IDA. Puoi trovare l'URL per scaricare un determinato IPSW da Apple online e ci sono numerosi strumenti pubblici (incluso memctl) in grado di decomprimere il kernelcache.
In IDA, seleziona "File" -> "File di script..." 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 degli indirizzi. Ciò significa che se il
kernelcache è stato analizzato manualmente prima dell'inizializzazione con kernelcache_process, i
risultati potrebbero non essere altrettanto approfonditi perché i nomi specificati dall'utente potrebbero bloccare la propagazione automatica dei nomi.
Tuttavia, non vi è inoltre alcuna garanzia che ida_kernelcache non rovini le analisi precedenti, quindi se
decidi di eseguire kernelcache_process su un file kernelcache che hai già analizzato, fai prima un
backup.
ida_kernelcache deve 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 delle 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
word di dimensione variabile da un indirizzo. read_struct legge un tipo di 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 word di dati e sui loro indirizzi in un intervallo.
build_struct: Questo modulo interno contiene utilità per popolare automaticamente una struct IDA in base a una sequenza di accessi alla struct.
class_struct:
Questo modulo fornisce funzioni per generare struct IDA che rappresentano tabelle di metodi virtuali C++ e
classi. initialize_vtable_structs esamina le tabelle dei metodi virtuali (symbolicate) 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 ciascuna 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 struttura. Consulta 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 ciascuna classe C++. Inoltre, ogni oggetto ClassInfo memorizza riferimenti al
ClassInfo della superclasse e al ClassInfo di tutte le sottoclassi dirette, rendendo facile
esaminare e attraversare la 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 sul flusso di dati usate dal resto di ida_kernelcache.
kernel:
Questo modulo fornisce le variabili globali base e prelink_info. base è l'indirizzo di base
dell'immagine del kernel (l'inizio dell'header 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 nota.
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
symbolicate 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 rendendoli più utili.
Di default, IDA sembra creare i nomi dei segmenti combinando una stima 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 in modo da includere l'identificatore del bundle,
il segmento Mach-O e la sezione Mach-O. Questo rende possibile, ad esempio, distinguere
tra __TEXT.__const e __DATA_CONST.__const. Questo modulo fornisce anche la funzione
kernelcache_kext (riesportata a livello principale) per determinare il kext che contiene l'indirizzo
specificato (solo nel vecchio formato kernelcache split-kext di iOS 11).