# Análise dinâmica: o app rodando sob instrumentação

> Frida, objection, interceptação de tráfego e por que uma função suspeita só vira achado confirmado quando o app está rodando de verdade.

- Autor: Marcelo Silva
- Publicado em: 2026-10-15
- Tema: Segurança
- Série: Segurança Mobile, parte 10 de 11 (https://marcelxsilva.dev/series/seguranca-mobile/)
- URL: https://marcelxsilva.dev/artigos/analise-dinamica-e-instrumentacao/

Os artigos anteriores desta série cobriram a análise estática: ler o código, o manifesto e o binário de um app sem executá-lo. Ela mostra o que um app **pode** fazer. A análise dinâmica responde a outra pergunta: o que ele **faz de fato**, quando está rodando, conectado à rede, manipulando dados reais.

Essa mudança de modo exige um ambiente diferente e uma categoria de ferramenta própria: a instrumentação em tempo de execução.

## Por que um ambiente de teste, não o app de produção de alguém

Testar a análise dinâmica de um app exige observar e, em muitos casos, alterar seu comportamento enquanto ele roda, o que inclui interceptar o tráfego de rede e inspecionar dados em memória. Fazer isso contra um app de terceiros, ou contra um backend de produção que não é seu, sem autorização, [pode configurar crime](https://www.planalto.gov.br/ccivil_03/_ato2011-2014/2012/lei/l12737.htm) na legislação brasileira, além de violar os termos de uso da maioria dos serviços. Por isso esse tipo de teste só deve ser feito em ambiente próprio, com autorização explícita, ou contra os [apps vulneráveis de propósito](https://mas.owasp.org/crackmes/) que a própria OWASP mantém para treino.

## Preparando um emulador com root

No Android, a análise dinâmica profunda (interceptar chamadas de função, driblar verificações locais) exige um aparelho com [root](https://source.android.com/docs/security/app-sandbox) ou, mais comumente para fins de teste, um emulador criado com uma imagem de sistema **Google APIs** (que tem root habilitado), em vez da imagem **Google Play** (sem root), usada normalmente por consumidores finais:

```bash
sdkmanager "system-images;android-34;google_apis;arm64-v8a"
avdmanager create avd -n pentest -k "system-images;android-34;google_apis;arm64-v8a"
emulator -avd pentest -writable-system &
adb root && adb remount
```

Com o emulador em modo de leitura e escrita (último comando acima), é possível remontar o sistema de arquivos e instalar as ferramentas de instrumentação direto no dispositivo.

## Frida: a base da instrumentação

O [Frida](https://frida.re/) é um framework de instrumentação dinâmica de código aberto que permite injetar scripts em JavaScript dentro de um processo em execução, para Android, iOS e várias outras plataformas. Na prática, isso significa interceptar a chamada de qualquer método (em Java, Objective-C ou código nativo) e substituir seu comportamento: por exemplo, fazer uma função que normalmente retorna `false` passar a retornar sempre `true`.

```bash
uv tool install frida-tools
uv tool install objection
```

Com o emulador de root pronto (passo anterior), falta subir o `frida-server` dentro dele, na mesma versão instalada na máquina:

```bash
frida --version
# baixe frida-server-<mesma versão>-android-arm64 em github.com/frida/frida/releases
adb push frida-server /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server && /data/local/tmp/frida-server &"
frida-ps -U | head
```

O [`objection`](https://github.com/sensepost/objection) é uma camada construída em cima do Frida que empacota as tarefas mais comuns de um pentest mobile em comandos prontos, sem exigir que o testador escreva o próprio script de instrumentação para cada uma:

```bash
adb install example.apk
objection -g com.exemplo.app explore
```

Dentro do `objection`, alguns comandos úteis logo de início:

```text
android root disable
android sslpinning disable
android hooking list activities
android keystore list
env
```

Um app com proteções anti-instrumentação (detectadas, por exemplo, pelo [APKiD](https://marcelxsilva.dev/artigos/scanners-automaticos/)) pode se recusar a abrir quando percebe a presença do Frida. Nesse caso, uma alternativa é reempacotar o próprio APK com o [Frida Gadget](https://frida.re/docs/gadget/) embutido, uma biblioteca que roda a instrumentação sem depender de um processo externo com privilégio elevado:

```bash
objection patchapk -s example.apk
```

## Interceptando o tráfego de rede

Para observar as requisições que o app faz, a técnica padrão é colocar um proxy de interceptação no meio da conexão, usando ferramentas como o [mitmproxy](https://mitmproxy.org/), o [HTTP Toolkit](https://httptoolkit.com/) ou o [Burp Suite](https://portswigger.net/burp):

```bash
brew install --cask http-toolkit
brew install --cask mitmproxy
```

O proxy instala sua própria autoridade certificadora (CA) no dispositivo de teste, o que permite decifrar o tráfego HTTPS para leitura, desde que o app aceite essa CA: abra o HTTP Toolkit e escolha "Android device via ADB", ou rode `mitmweb --listen-port 8080` e instale a CA gerada no emulador manualmente.

É exatamente aí que entra o [certificate pinning](https://marcelxsilva.dev/artigos/tls-pinning-e-armazenamento/), descrito no artigo anterior: um app com pinning corretamente implementado rejeita a CA do proxy, mesmo que ela esteja instalada como confiável pelo sistema. Já com o `objection` isso costuma bastar (`android sslpinning disable`, visto acima), mas para testar o comportamento da aplicação com mais controle, scripts de "unpinning" (como os do projeto [frida-interception-and-unpinning](https://github.com/httptoolkit/frida-interception-and-unpinning), mantido pela equipe do HTTP Toolkit) usam o Frida para interceptar e neutralizar a checagem de pinning em tempo de execução:

```bash
git clone https://github.com/httptoolkit/frida-interception-and-unpinning
cd frida-interception-and-unpinning
frida -U -l config.js -l android/android-certificate-unpinning.js -f com.exemplo.app
```

Com o tráfego visível, os pontos clássicos de revisão são: token de autenticação exposto numa URL (em vez de num header, por exemplo) ou num log; respostas da API que vazam dado de outro usuário quando um identificador é trocado na requisição ([IDOR](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/04-Testing_for_Insecure_Direct_Object_References), uma das categorias mais comuns de falha de autorização); e se o backend aceita, fora do app, uma credencial de cliente que só deveria funcionar vindo do app legítimo.

## Componentes expostos, de verdade

A [fase estática de manifesto](https://marcelxsilva.dev/artigos/manifest-e-superficie-de-ataque/) identifica quais componentes estão declarados como exportados. A fase dinâmica confirma o que acontece quando eles de fato são chamados:

```bash
adb shell am start -n com.exemplo.app/.MainActivity
adb shell am start -a android.intent.action.VIEW -d "https://exemplo.com/rota?param=teste"
```

O primeiro comando abre uma activity específica como se fosse outro app fazendo a chamada; o segundo testa um deep link diretamente. Para service, receiver e content provider, que não têm um atalho tão simples quanto uma activity, ferramentas especializadas como o [drozer](https://github.com/WithSecureLabs/drozer) automatizam o teste:

```bash
uv tool install drozer
```

## O que fica gravado no aparelho

Com acesso root ao sistema de arquivos, dá para inspecionar diretamente o que o app grava: preferências compartilhadas, bancos de dados locais (incluindo o que uma camada como o `AsyncStorage`, comum em React Native, usa por baixo) e os logs do sistema:

```bash
adb shell run-as com.exemplo.app ls -R /data/data/com.exemplo.app/
adb shell "su -c 'ls -R /data/data/com.exemplo.app/shared_prefs /data/data/com.exemplo.app/databases'"
adb logcat --pid=$(adb shell pidof com.exemplo.app)
```

É nesse momento que um dado sensível salvo "temporariamente" em texto puro, token, informação pessoal, aparece de forma concreta, em vez de apenas suspeitado pela leitura do código.

## iOS: jailbreak ou Gadget

No iOS, o mesmo nível de instrumentação normalmente exige um dispositivo com [jailbreak](https://www.eff.org/deeplinks/2024/03/apples-walled-garden-problem), ou, como alternativa sem jailbreak, reempacotar o IPA com o Frida Gadget, de forma equivalente ao que acontece no Android:

```bash
objection patchipa --source example.ipa --codesign-signature "<identidade>"
objection -g com.exemplo.app explore
```

A partir daí, o `objection` oferece os mesmos atalhos adaptados à plataforma:

```text
ios sslpinning disable
ios keychain dump
ios nsuserdefaults get
ios plist cat <arquivo>
```

## Estático e dinâmico, lado a lado

Nenhuma das duas análises substitui a outra. Uma função suspeita encontrada lendo o código (estática) só vira um achado confirmado quando reproduzida com o app rodando (dinâmica); e um comportamento estranho observado em tempo de execução só se transforma numa correção acionável quando alguém encontra a linha exata de código que o origina. É justamente esse fechamento de ciclo, do candidato a achado até o registro formal, o assunto do último artigo desta série.
