Voltar ao laboratório
Tutorial Android 12 min

Frida no Android: Instrumentação Dinâmica, Bypass e Reempacotamento de APKs

26 de maio de 2026

O que é o Frida

Frida é um framework de instrumentação dinâmica que injeta um agente JavaScript em processos em execução. No contexto de pentest Android, ele permite interceptar chamadas de método, modificar retornos e bypassar proteções em tempo real — sem precisar do código-fonte do app.


Ambiente de laboratório

Requisitos:

  • Dispositivo Android com root (físico ou emulador como Genymotion/AVD rooteado)
  • adb instalado e dispositivo conectado
  • Python 3 para o servidor Frida
# Instala o Frida CLI e ferramentas
pip install frida-tools

# Verifica a versão
frida --version

Baixar o frida-server para o dispositivo:

# Descobre a arquitetura do dispositivo
adb shell getprop ro.product.cpu.abi
# Exemplo de saída: arm64-v8a

# Baixa o frida-server correspondente em:
# https://github.com/frida/frida/releases
# Ex: frida-server-16.x.x-android-arm64

# Envia para o dispositivo
adb push frida-server /data/local/tmp/
adb shell chmod 755 /data/local/tmp/frida-server

# Inicia o servidor (em segundo plano)
adb shell /data/local/tmp/frida-server &

Hooking básico de método Java

Estrutura base de um script Frida:

Java.perform(() => {
  const TargetClass = Java.use('com.exemplo.app.MinhaClasse')

  TargetClass.metodoAlvo.implementation = function (param) {
    console.log('[*] metodoAlvo chamado com:', param)
    const resultado = this.metodoAlvo(param) // chama o original
    console.log('[*] retorno original:', resultado)
    return resultado // ou retorna valor modificado
  }
})

Executando o script:

frida -U -f com.exemplo.app -l meu_script.js --no-pause

| Flag | Significado | |------|-------------| | -U | Conecta via USB | | -f | Spawna o app (cold start) | | -l | Script a carregar | | --no-pause | Não pausa na inicialização |


Bypass de SSL Pinning

SSL Pinning é implementado de formas diferentes. Abaixo os bypasses mais comuns:

OkHttp / CertificatePinner

Java.perform(() => {
  const CertificatePinner = Java.use('okhttp3.CertificatePinner')

  CertificatePinner.check.overload('java.lang.String', 'java.util.List')
    .implementation = function (hostname, peerCertificates) {
      console.log('[*] SSL Pinning bypassado para:', hostname)
      // Não chama o original — remove a validação
    }
})

TrustManager customizado

Java.perform(() => {
  const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager')
  const SSLContext = Java.use('javax.net.ssl.SSLContext')

  const TrustManagerImpl = Java.registerClass({
    name: 'com.frida.TrustManager',
    implements: [X509TrustManager],
    methods: {
      checkClientTrusted(chain, authType) {},
      checkServerTrusted(chain, authType) {},
      getAcceptedIssuers() { return [] },
    },
  })

  const ctx = SSLContext.getInstance('TLS')
  ctx.init(null, [TrustManagerImpl.$new()], null)
  SSLContext.setDefault(ctx)
  console.log('[*] TrustManager substituído')
})

Dica: O script universal ssl-pinning-bypass do frida-codeshare cobre a maioria dos casos com uma linha: frida-codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -U -f com.exemplo.app


Bypass de Root Detection

Java.perform(() => {
  // RootBeer
  try {
    const RootBeer = Java.use('com.scottyab.rootbeer.RootBeer')
    RootBeer.isRooted.implementation = function () {
      console.log('[*] RootBeer.isRooted bypassado')
      return false
    }
  } catch (_) {}

  // Verificação via Runtime.exec
  const Runtime = Java.use('java.lang.Runtime')
  Runtime.exec.overload('java.lang.String').implementation = function (cmd) {
    if (cmd.indexOf('su') !== -1) {
      console.log('[*] Bloqueando execução de:', cmd)
      return null
    }
    return this.exec(cmd)
  }
})

Desempacotamento e reempacotamento de APK com APKTool

O APKTool decompila o APK em smali (bytecode legível) e recursos — útil para modificar o app antes de reanálise.

Instalação

# Linux
wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool
wget https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.x.x.jar
chmod +x apktool
sudo mv apktool apktool_2.x.x.jar /usr/local/bin/

Desempacotar

apktool d app.apk -o app_decompilado/

Estrutura gerada:

app_decompilado/
├── AndroidManifest.xml     # Manifesto decodificado
├── res/                    # Recursos (layouts, strings)
├── smali/                  # Bytecode Dalvik em texto
└── apktool.yml             # Metadados do APKTool

Modificar e reempacotar

# Após modificações no smali ou recursos:
apktool b app_decompilado/ -o app_modificado.apk

# Assinar o APK (necessário para instalar)
keytool -genkey -v -keystore minha_chave.keystore -alias alias_name \
        -keyalg RSA -keysize 2048 -validity 10000

jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
          -keystore minha_chave.keystore app_modificado.apk alias_name

# Instalar no dispositivo
adb install app_modificado.apk

Atenção: Apps com Play Integrity ou SafetyNet detectam APKs não originais. Nesses casos, use o Frida sem modificar o APK.


Detectando anti-Frida em runtime

Alguns apps detectam o Frida verificando o nome do processo ou /proc/self/maps. Para contornar:

// Oculta o nome do processo frida-server
Java.perform(() => {
  const ActivityThread = Java.use('android.app.ActivityThread')
  ActivityThread.currentProcessName.implementation = function () {
    return 'com.exemplo.app' // retorna nome legítimo
  }
})

Para detecções baseadas em /proc/maps, considere usar frida-gadget embutido no APK em vez do frida-server separado.


Referências

Frida no Android: Instrumentação Dinâmica, Bypass e Reempacotamento de APKs — APCosta Lab — APCosta