Segurança

Analisando logs de Kernel Panic do iOS | 8kSec

O texto discute como analisar logs de kernel panic no iOS, explicando causas comuns e métodos para extrair esses logs, seja por meio de ferramentas ou diretamente pelo sistema operacional. Os logs seguem uma convenção de nomenclatura específica e contêm informações cruciais sobre a causa do problema, como a string de panic que descreve o erro específico. Além disso, são apresentadas técnicas para simplificar esses arquivos e identificar possíveis problemas relacionados ao kernel ou módulos adicionais.

Compartilhar
Analyzing iOS Kernel Panic Logs | 8kSec

O que é um Kernel Panic?

Neste blog, discutiremos a análise de logs de kernel panic do iOS. Um kernel panic ocorre quando o núcleo do sistema operacional encontra um erro fatal. Este erro é tão grave que o kernel não pode continuar funcionando ou recuperar o sistema em um estado estável seguro. Por padrão, o núcleo do iOS reinicia no caso de um panic.

Causas comuns de kernel panics incluem:

  • Hardware defeituoso ou incompatível.
  • Bugs de software no núcleo ou em componentes de nível de sistema.
  • Extensões do kernel mal funcionando.
  • Corrupção de memória ou sobreposições.

Oftentimes, pesquisadores de segurança examinam os logs de Kernel panic para identificar se o Panic ocorreu devido a uma vulnerabilidade.

Em um dispositivo iOS. Panics podem ser identificados indo em (Configurações -> Privacidade -> Análise) ou no sistema de arquivos indo em (/private/var/mobile/Library/Logs/CrashReporter) se você tiver um iOS jailbroken. Em alguns casos, pode haver arquivos dentro da pasta CrashReporter então é sempre uma boa ideia fazer uma pesquisa recursiva pelo log de panic.

Os logs de kernel panic seguem uma convenção de nomenclatura específica: panic-full-yyyy-mm-dd-HHMMSS.000.ips. Como a mesma pasta também contém logs de crash do usuário, esta convenção de nomenclatura ajuda a identificar um log de Kernel panic de um log de crash do usuário.

No exemplo abaixo, você pode ver um dos logs de Kernel panic presentes em um dispositivo iOS jailbroken.

Arquivo de log de kernel panic visível na pasta CrashReporter no dispositivo iOS jailbroken

E este é como um log de Kernel Panic aparece. Neste blog, tentaremos fazer sentido dele.

Arquivo de log bruto do kernel iOS mostrando a string de panic, backtrace e valores dos registradores

Também é possível simplesmente extrair o arquivo de log de Kernel panic usando ferramentas como idevicecrashreport do https://libimobiledevice.org/.

Ferramenta idevicecrashreport extraíndo log de kernel panic de um dispositivo iOS via USB

Além disso, também é possível extrair os logs de Panic do dispositivo usando o Xcode conectando seu dispositivo ao computador e garantindo que ele seja reconhecido pelo Xcode, então indo em Window -> Devices and Simulators -> Open Recent Logs

Janela Xcode Devices and Simulators com a opção Open Recent Logs destacada

Isto levará você ao Finder onde ele extraiu todos os logs e você pode identificar os logs de Kernel Panic usando a mesma convenção de nomenclatura panic-full-yyyy-mm-dd-HHMMSS.000.ips

Finder mostrando arquivos de log extraídos incluindo arquivos kernel panic .ips

Agora que vimos como podemos extrair um log de Kernel Panic do dispositivo, vamos tentar fazer sentido do arquivo de Panic.

A String de Panic

Dentro de um arquivo de kernel panic, a string de panic refere-se a uma linha específica de texto que descreve o motivo para o panic. É geralmente uma mensagem de erro concisa ou um identificador de código que fornece uma pista sobre o que deu errado no kernel.

Quando examinando um arquivo de kernel panic, localizar e analisar a string de panic é frequentemente uma das primeiras etapas para diagnosticar o problema. Ela pode indicar problemas como corrupção de memória, falhas de hardware, bugs de software ou drivers incompatíveis. Entendendo a string de panic e seu contexto associado, pesquisadores podem limitar as causas potenciais e trabalhar em direção à resolução do problema subjacente. Como você pode ver mesmo no código-fonte XNU, a função panic() toma uma string como argumento que é a String de Panic.

Código-fonte do kernel XNU mostrando a assinatura da função panic() que recebe um argumento de string

Por exemplo, na imagem abaixo do arquivo Panic você verá a String de Panic presente dentro do arquivo.

Arquivo de pane do kernel mostrando a linha da string de pane que identifica o motivo da falha

Se você tiver sorte, pode encontrar a string de pane presente no próprio código do núcleo XNU fornecido em opensource.apple.com. Nesse caso, você poderá identificar o código exato que está causando o problema e isso facilitará a análise.

No caso de não estarem presentes, apenas abrindo o kernelcache e cruzando referências com a string de pane pode fornecer uma ideia do que aconteceu, já que as strings não são obfuscadas dentro do kernel iOS.

Simplificando o arquivo de pane

O seguinte script chamado panicparser.py https://gist.github.com/PsychoTea/d9ca14d2687890f15900d901f600bf6a pode ser usado para converter o arquivo de pane do kernel em um formato mais legível.

Saída do script panicparser.py convertendo o log de pane do kernel em um formato mais legível

A string de pane é visível na primeira linha após o comando.

Alguns dos pontos notáveis são:

  • Versão do kernel: Darwin Kernel Version 22.0.0: Terça-feira, 16 de agosto de 2022, 20:52:01 PDT; root:xnu-8792.2.11.0.1~1/RELEASE_ARM64_T8101
  • ID do kernel: 72C7327A-D999-3613-8F7B-C86E542122D3
  • Slide do kernelcache: 0x00000000266bc000
  • Base do kernelcache: 0xfffffff02d6c0000
  • Slide do kernel: 0x0000000027314000
  • Base do texto do kernel: 0xfffffff02e318000
  • Slide de execução do texto do kernel: 0x00000000273cc000

A inclusão da ID do kernel permite que a Apple localize o kernel e simbolize-o automaticamente.

Você também pode ver a tarefa responsável pela pane e o backtrace da thread na saída.

Panicado Task:
  Task: 0xffffffecfe770c50    (refere-se ao endereço de memória da estrutura de tarefa)
  Threads: 1                 (a tarefa tinha apenas uma thread ativa)
  Processo: pid 395: xpcproxy (process ID 395, o xpcproxy gerencia a comunicação interprocessual)
Panicado Thread:
  Endereço da Thread: 0xffffffede1884340  (endereço de memória da thread que entrou em pane)
  Backtrace: 0xffffffe882d83320       (endereço inicial da pilha do backtrace)
  ID da Thread: 7480                     (identificador único para esta thread)

O backtrace fornece uma lista de chamadas de função (endereços de retorno) que levaram à pane do kernel. Cada linha inclui:

Os endereços no backtrace estão todos deslizados. Para converter o backtrace em endereços reais, precisamos subtrair o valor slide do kernel. O valor de Slide do Kernel é 0x0000000027314000 no log de pane.

Para cada endereço do backtrace (denotado como lr):

  • Endereço Real = Endereço no Backtrace - Slide do Kernel

Por exemplo, usando o slide do kernel fornecido (0x0000000027314000), aqui está o backtrace convertido:

0xfffffff007107ef8 - 0x0000000027314000 = 0xfffffff0043fc4f8

Também é importante notar que os endereços iniciados com 0xffffff7f... geralmente pertencem a extensões de kernel (kexts), que são módulos terceiros ou fornecidos pelo sistema. Se esses aparecerem no backtrace, o problema pode estar relacionado à respectiva kext. No entanto, neste caso, isso não é verdadeiro, então parece que o problema provavelmente está relacionado à imagem principal do kernel.

Simbolizando um Arquivo de Kernel Panic

Embora tenhamos os endereços, seria bom colocar símbolos para esses endereços. Uma das maneiras de fazer isso é simbolizar o arquivo de Kernel Panic. Existem várias ferramentas que podem ser usadas para simbolizar o arquivo de Panic, mas a que vamos usar é ipsw (https://github.com/blacktop/ipsw).

A primeira coisa seria baixar o arquivo ipsw correspondente ao dispositivo e à versão do iOS. Os detalhes da versão do iOS e da Versão de Produto para um dispositivo podem ser encontrados usando ideviceinfo.

Você pode então ir até ipsw.me e baixar o arquivo ipsw correspondente de ipsw.me

Uma vez que o ipsw é baixado, estamos agora prontos para usar ipsw para simbolizar o arquivo de Kernel panic. Como podemos ver nas opções de ajuda, precisamos do arquivo ipsw e do arquivo de Panic correspondente.

saída da ferramenta ipsw mostrando as opções para simbolização de kernel panic incluindo argumentos de arquivos ipsw e panic

comando ipsw sendo executado com o arquivo ipsw baixado e o log de Kernel panic para simbolização

Vamos então executar o comando de simbolização do kernelcache

comando de simbolização do kernelcache sendo executado contra o kernelcache extraído do ipsw

saída da simbolização ipsw mostrando endereços de funções do kernel com nomes de símbolos resolvidos

trilha completa simbolizada de Kernel panic mostrando nomes de funções em vez de endereços brutos

E agora podemos ver os símbolos no modo userland. Outra opção seria executar o mesmo comando acima com a opção —unslide para garantir que os endereços sejam convertidos em endereços estáticos reais que podem ser identificados no Kernelcache.

Identificando a Causa Raiz

Quando tentamos identificar a causa raiz do problema, vamos começar com a string de Panic.

pmap_mark_page_as_ppl_page_internal: página ainda tem mapeamentos, pa=0x8bf880000 @pmap_data.c:1101

código-fonte XNU mostrando a função pmap_mark_page_as_ppl_page_internal com a string de panic correspondente na linha 1092

Verificando no código-fonte do XNU e dentro da função pmap_mark_page_as_ppl_page_internal, encontramos a string de panic na linha #1092 em uma versão do XNU mais próxima àquela usada no iOS (Note que as versões do XNU para o iOS não são código aberto) que corresponde com a string de Panic que vemos no arquivo Log. Como mencionado nos comentários e pesquisando um pouco, aprendendo de https://github.com/felix-pb/kfd/blob/main/writeups/exploiting-puafs.md, podemos concluir que isso é provavelmente devido a um falha de exploração onde a página dada, supostamente para ser usada, está mapeada fora da janela física de PPL, significando que uma página liberada suposta para ser alocada para o PPL tem mapeamentos fora da janela física do PPL. Isso é verificado pela função e em caso de falha um panic é acionado. Este problema ocorre durante a exploração de uma exploração que usa um primitivo PUAF (Page Use After Free) para garantir que uma página virtual do endereço da memória de userland não tenha mapeamentos para o endereço físico, mesmo que agora o endereço físico já esteja marcado como pronto para uso pelo Kernel, e neste caso, o problema ocorre devido a um verificação adicional por código baseado em PPL que verifica se uma página física mapeada para PPL tem mapeamentos fora da janela física da página.

Se você está interessado em aprender mais sobre este primitivo PUAF, confira nosso curso “Offensive iOS Internals” no Academia 8ksec.

Agora é claro que neste caso fomos sortudos que a string de panic foi identificada na base do código XNU, mas isso pode não ser o caso sempre e você deve tentar identificar a string no Kernelcache e cruzar referências para encontrar o lugar onde ocorreu o crash.

Conclusão

A análise de logs de Kernel Panic do iOS é uma habilidade essencial para diagnosticar e resolver problemas de nível de sistema, especialmente para pesquisadores de segurança e desenvolvedores. Os Kernel Panics podem ter origem em uma ampla gama de causas, incluindo hardware defeituoso, bugs de software, corrupção de memória ou extensões do kernel mal funcionando. Ao extrair cuidadosamente e analisar os logs, você pode obter insights valiosos sobre a causa raiz do Kernel Panic.

Este blog o guiou pelo processo de:

  • Extrair logs de Kernel Panic de um dispositivo iOS usando ferramentas como Xcode, idevicecrashreport ou diretamente do sistema de arquivos.
  • Identificar a string de panic, que fornece a primeira pista sobre a natureza da queda.
  • Simplificar e simbolizar o log de panic usando scripts como panicparser.py e ferramentas como ipsw, o que ajuda a tornar os logs mais legíveis e práticos.
  • Interpretar detalhes-chave, como a tarefa em pânico, backtrace da thread e endereços slid, para localizar o problema no kernel ou nas extensões do kernel.
  • Simbolizar os endereços do kernel para mapeá-los para funções ou rotinas específicas, permitindo uma análise mais profunda.
  • Identificar a Causa Raiz do Panic usando análises adicionais.

Para pesquisadores de segurança, os logs de Kernel Panic são particularmente úteis para identificar potenciais vulnerabilidades. Ao analisar padrões em quedas e backtraces, você pode descobrir problemas sutis que podem levar a explorações de segurança ou gargalos de desempenho.

A análise de Kernel Panic pode parecer intimidadora no início, mas com as ferramentas e metodologia corretas, ela se torna uma maneira poderosa de entender e resolver problemas de nível baixo do sistema. Esperamos que este blog tenha fornecido a você uma base sólida para começar a investigar Kernel Panics efetivamente.

Fonte original

Conteúdo traduzido e adaptado pela redação do Notícias Mobile. Confira também a matéria na fonte original.

Leia a matéria completa