
Um Kit de Ferramentas IDA para analisar kernelcaches do iOS.
Este fork foi atualizado para funcionar no IDA 9.x / Python 3 / iOS 27.0 beta 1
ida_kernelcache é um módulo IDAPython para o IDA Pro que facilita o trabalho com kernelcaches do iOS. O módulo fornece funções para:
__PRELINK_INFO do kernel em um dicionário Python.__got e funções stub em seções __stubs.A função de processamento principal foi projetada para ser executada antes de qualquer análise manual ou engenharia reversa. Com as configurações padrão, o IDA tende a perder muitas informações úteis no kernelcache. Esses scripts ajudam o IDA, aproveitando a estrutura conhecida do kernelcache para propagar automaticamente informações úteis.
Além da funcionalidade padrão do módulo, o ida_kernelcache contém vários scripts para facilitar a análise do kernelcache do iOS. Por exemplo, você pode usar os scripts para gerar automaticamente estruturas C usadas por uma função.
Muitas das técnicas usadas no ida_kernelcache foram desenvolvidas para e emprestadas diretamente do memctl.
O ida_kernelcache foi testado com o IDA Pro 6.95 em kernelcaches para as versões do iOS 10.1.1, 11.0, 11.2, 11.3.1 e 12.0 beta. Atualmente, apenas kernelcaches Arm64 do iOS 10 em diante são suportados.
Você já precisa ter um arquivo kernelcache descomprimido carregado no IDA. Você pode encontrar a URL para baixar um IPSW específico da Apple online, e existem várias ferramentas públicas (incluindo o memctl) capazes de descomprimir o kernelcache.
No IDA, selecione "File" -> "Script file..." na barra de menu, depois escolha o script
ida_kernelcache.py no diretório principal. Isso carregará o módulo ida_kernelcache no interpretador
IDAPython sob os nomes ida_kernelcache e kc. No prompt IDAPython, digite
kc.kernelcache_process() e pressione Enter para começar a analisar o kernelcache. Esta função
realiza todas as análises principais suportadas pelo ida_kernelcache. A função será executada por
vários minutos enquanto o IDA identifica e analisa novas funções.
O ida_kernelcache tentará não sobrescrever nomes de usuário para endereços. Isso significa que se o
kernelcache foi analisado manualmente antes da inicialização com kernelcache_process, os resultados
podem não ser tão completos, pois nomes especificados pelo usuário podem bloquear a propagação
automática de nomes. No entanto, também não há garantia de que o ida_kernelcache não estrague análises
anteriores; portanto, se você decidir executar kernelcache_process em um arquivo kernelcache já
analisado, faça um backup primeiro.
O ida_kernelcache deve ser carregado via ida_kernelcache.py; os submódulos no diretório
ida_kernelcache não devem ser carregados diretamente. No entanto, o ida_kernelcache expõe a
funcionalidade de muitos desses submódulos. Aqui está o que cada um deles faz:
ida_utilities:
Este módulo encapsula algumas funções do IDA para fornecer uma API mais fácil de usar.
Particularmente úteis são is_mapped, read_word, read_struct, force_function e ReadWords.
is_mapped verifica se um endereço está mapeado e, opcionalmente, se contém um valor conhecido.
read_word lê uma palavra de tamanho variável de um endereço. read_struct lê um tipo de estrutura
em um dicionário Python ou objeto acessor Python, o que facilita muito a análise de estruturas de
dados. force_function tenta vários truques para converter um endereço no início de uma função no
IDA. ReadWords é um gerador para iterar sobre palavras de dados e seus endereços em um intervalo.
build_struct: Este módulo interno contém utilitários para preencher automaticamente uma estrutura IDA com base em uma sequência de acessos à estrutura.
class_struct:
Este módulo fornece funções para gerar estruturas IDA que representam tabelas de métodos virtuais C++
e classes. initialize_vtable_structs escaneia as tabelas de métodos virtuais (simbolizadas) e cria
estruturas IDA para armazenar ponteiros de métodos virtuais. initialize_class_structs realiza uma
análise de fluxo de dados nos métodos virtuais para identificar acessos aos campos de cada classe e,
em seguida, constrói estruturas IDA para representar as classes. Instruções que parecem referenciar
um campo também são convertidas em referências de offset de estrutura. Consulte a docstring do módulo
para mais detalhes.
classes:
Este módulo define o tipo ClassInfo que armazena informações sobre classes C++ no kernelcache e
fornece a função collect_class_info para escanear o kernelcache em busca de classes e preencher o
dicionário global class_info com um mapa de nomes de classes para objetos ClassInfo. O tipo
ClassInfo registra o nome da classe, a instância OSMetaClass, a tabela de métodos virtuais e o nome
da superclasse para cada classe C++. Além disso, cada objeto ClassInfo armazena referências ao
ClassInfo da superclasse e ao ClassInfo de todas as subclasses diretas, facilitando a análise e a
travessia da hierarquia de classes. collect_class_info também armazena o conjunto de todas as
tabelas de métodos virtuais no conjunto global vtables.
data_flow: Este módulo interno contém operações de fluxo de dados usadas pelo resto do ida_kernelcache.
kernel:
Este módulo fornece as variáveis globais base e prelink_info. base é o endereço base da imagem
do kernel (o início do cabeçalho Mach-O do kernel). prelink_info é o dicionário __PRELINK_INFO
analisado.
kplist:
Este módulo fornece a função kplist_parse para analisar plists no estilo do kernel.
metaclass:
Este módulo fornece a função initialize_metaclass_symbols que adiciona um símbolo para cada
instância OSMetaClass conhecida.
offset:
Este módulo fornece as funções initialize_data_offsets e initialize_offset_symbols. A primeira
escaneia os segmentos em busca de ponteiros que possam ser convertidos em offsets. A última simboliza
offsets na seção __got de cada kext se o destino do offset tiver um símbolo.
segment:
Este módulo fornece a função initialize_segments para renomear os segmentos do IDA para serem mais
úteis. Por padrão, o IDA parece criar os nomes dos segmentos combinando um palpite do identificador
do pacote com a seção Mach-O que descreve a região. initialize_segments extrai o identificador real
do pacote do dicionário __PRELINK_INFO e renomeia cada segmento para incluir o identificador do
pacote, o segmento Mach-O e a seção Mach-O. Isso torna possível, por exemplo, distinguir entre
__TEXT.__const e __DATA_CONST.__const. Este módulo também fornece a função kernelcache_kext
(reexportada no nível superior) para determinar o kext que contém o endereço especificado (apenas no
formato antigo de kernelcache split-kext do iOS 11).