Introdução
Bem-vindo à parte 4 da nossa série sobre uso avançado do Frida. Na parte três de nossos posts sobre o Frida, discutimos o que é XPC, como usá-lo e como interceptar com o Frida.
Neste post do blog, vamos discutir como usar as ferramentas XPC para este trabalho, algumas delas são xpcspy e gxpc. A ferramenta xpcspy já é bem coberta com tutoriais, enquanto o gxpc é uma nova ferramenta inspirada no xpcspy. Ela se comporta da mesma maneira que o xpcspy com pequenas adições, como a análise recursiva de mensagens (se o dicionário conter outro dicionário, ele será analisado também), além disso, ela suporta xpc_connection_set_event_handler que imprime o endereço da implementação do bloco.
Instalação
Assim como com frida-go, o gxpc suporta macOS, Linux e Android. Usaremos o macOS como máquina anfitriã. Primeiro precisamos instalar Go e baixar frida-core-devkit para nossa máquina.
Para nossa máquina, vamos baixar macos-arm64 já que estamos trabalhando em um M1 e para a versão do Frida 16.0.19, é frida-core-devkit-16.0.19-macos-arm64.tar.xz.
Após baixar o devkit, vamos mover os arquivos libfrida-core.a e frida-core.h para locais apropriados.
Agora que temos tudo pronto, podemos executar go install github.com/nsecho/gxpc@latest.

Como o gxpc funciona?
O gxpc funciona usando as ligações do Frida que são escritas em Go usando frida-go. As ligações do Frida permitem ao usuário usar a funcionalidade do Frida com outras linguagens, como Python, Swift, node.js, Go, etc. O Go tem a opção de interagir com o código C usando cgo. Para vincular o frida-go, precisamos ter as bibliotecas dinâmicas do frida-core instaladas no sistema bem como o arquivo de cabeçalho frida-core.h que está incluído dentro do frida-core-devkit que precisamos instalar.
No nível interno, o gxpc rastreia funções específicas xpc_* que podemos ver no arquivo source.js.

Podemos ver o comentário Intercept these functions que nos diz imediatamente o que será feito com essas variáveis. Ele está usando a API Module.findExportByName que vimos em posts anteriores.
A seguir, temos uma série de funções usadas para extrair dados do dicionário ou array, como xpc_dictionary_get_value ou xpc_copy_description.
Para cada função que deve ser interceptada, é chamado o método Interceptor.attach. Uma vez que essas funções são chamadas, a função parseAndSendDictData é chamada com o nome da função como primeiro parâmetro, xpc_connection_t como segundo parâmetro e xpc_object_t como terceiro argumento. A função parseAndSendDictData cria um dicionário JSON e extrai os dados do xpc_object_t para objetos JavaScript. Uma vez que todos os objetos são analisados, eles são adicionados ao dicionário e enviados para o código Go usando a função send do Frida.
Usando gxpc
Agora que instalamos o gxpc e vimos como ele funciona, vamos conectar nosso iPhone com um cabo USB e confirmar que o dispositivo está conectado usando gxpc -l para listar os dispositivos.
Podemos ver que temos nossos dispositivos padrão locais e de socket disponíveis bem como o novo dispositivo iPhone conectado do tipo USB.
Por padrão, o gxpc se conectará ao dispositivo USB se um estiver conectado. Também podemos anexar ao processo pelo nome (locationd, SpringBoard) ou por PID. Temos a opção de criar uma instância do binário onde o processo será retomado assim que o script for carregado.
Vamos nos conectar ao locationd, que é o principal daemon responsável pelos dados de localização. Para fazer isso, usaremos gxpc -n locationd.

Após a execução, podemos ver imediatamente uma série de funções xpc_dictionary_set_string sendo interceptadas. Podemos criar uma lista negra para conexões específicas usando a bandeira -b ou --blacklist para o comando gxpc. Neste caso, vamos listar como negros as criações de dicionários.

A ferramenta retornará muitas funções sendo acionadas, para filtrar ainda mais os dados, vamos pesquisar na terminal pela string longitude.

Podemos ver que encontramos a correspondência dentro do bplist17 que é enviado usando a função xpc_connection_send_notification. Os dados contêm muita informação útil, como longitude, latitude, precisão etc.
Agora podemos usar a mesma abordagem para analisar diferentes aplicativos/binários e ver com quais aplicações/daemons eles estão se comunicando e qual é o formato dessa comunicação. Isso pode nos dar mais oportunidades de encontrar vulnerabilidades.

