MASTG-TECH-0034: Rastreamento de Native Code

O rastreamento de métodos nativos pode ser realizado com relativa facilidade em comparação com o rastreamento de métodos Java. frida-trace é uma ferramenta CLI para rastrear dinamicamente chamadas de funções. Ele torna trivial o rastreamento de funções nativas e pode ser muito útil para coletar informações sobre um aplicativo.

Para usar o frida-trace, um servidor Frida deve estar em execução no dispositivo. Um exemplo para rastrear a função open da libc usando frida-trace é demonstrado abaixo, onde -U conecta ao dispositivo USB e -i especifica a função a ser incluída no rastreamento.

frida-trace -U -i "open" com.android.chrome

Observe como, por padrão, apenas os argumentos passados para a função são exibidos, mas não os valores de retorno. Nos bastidores, o frida-trace gera um pequeno arquivo de handler JavaScript por função correspondente na pasta auto-gerada __handlers__, que o Frida então injeta no processo. Você pode editar esses arquivos para usos mais avançados, como obter o valor de retorno das funções, seus parâmetros de entrada, acessar a memória, etc. Consulte a JavaScript API do Frida para mais detalhes.

Neste caso, o script gerado que rastreia todas as chamadas para a função open na libc.so está localizado em __handlers__/libc.so/open.js e tem a seguinte aparência:

{
  onEnter: function (log, args, state) {
    log('open(' +
      'path="' + args[0].readUtf8String() + '"' +
      ', oflag=' + args[1] +
    ')');
  },


  onLeave: function (log, retval, state) {
      log('\t return: ' + retval);      \\ edited
  }
}

No script acima, onEnter cuida de registrar as chamadas para esta função e seus dois parâmetros de entrada no formato correto. Você pode editar o evento onLeave para imprimir os valores de retorno, como mostrado acima.

Observe que a libc é uma biblioteca bem conhecida, e o Frida é capaz de derivar os parâmetros de entrada de sua função open e registrá-los automaticamente de forma correta. Mas esse não será o caso para outras bibliotecas ou para código Android Kotlin/Java. Nesse caso, você pode querer obter as assinaturas das funções de interesse consultando a documentação do Android Developers ou fazendo primeiro a engenharia reversa do aplicativo.

Outra coisa a notar na saída acima é que ela é colorida. Um aplicativo pode ter várias threads em execução, e cada thread pode chamar a função open independentemente. Ao usar esse esquema de cores, a saída pode ser facilmente segregada visualmente para cada thread.

O frida-trace é uma ferramenta muito versátil e há várias opções de configuração disponíveis, como:

  • Incluir -I e excluir -X módulos inteiros.
  • Rastrear todas as funções JNI em um aplicativo Android usando -i "Java_*" (observe o uso de um glob * para corresponder a todas as funções possíveis que começam com "Java_").
  • Rastrear funções por endereço quando não há símbolos de nome de função disponíveis (binários stripped), por exemplo: -a "libjpeg.so!0x4793c".
frida-trace -U -i "Java_*" com.android.chrome

Muitos binários são stripped e não têm símbolos de nome de função disponíveis. Nesses casos, uma função também pode ser rastreada usando seu endereço.

frida-trace -p 1372 -a "libjpeg.so!0x4793c"