O que acontece quando você abre um APK
Um APK é basicamente um arquivo ZIP com uma estrutura padronizada. Se você renomear a extensão para .zip e abrir em qualquer descompactador, vai ver o mesmo conteúdo. A diferença é que o Android sabe interpretar esse formato nativamente, por isso ele funciona como pacote de instalação. Dentro do arquivo você encontra classes compiladas, recursos, manifesto e bibliotecas nativas organizados em diretórios específicos. Nada de mágica, só estrutura. O problema é que boa parte das pessoas que tentam mexer com isso pela primeira vez não sabe por onde começar e acaba gastando horas sem chegar a lugar nenhum.
What is inside apk android
A estrutura básica se divide em partes que cada uma cumpre uma função diferente. O arquivo classes.dex contém o código Java ou Kotlin compilado para Dalvik. O Android usa uma máquina virtual própria, então o bytecode convencional do Java não funciona diretamente — ele precisa passar por uma etapa de transpilação. O AndroidManifest.xml define permissões, componentes, versão do SDK e várias configurações que o sistema lê antes de qualquer coisa. Os recursos ficam em res/values, res/layout, res/drawable e diretórios similares. Tudo aquilo que é texto, imagem, cor ou layout no app é separado aqui. Bibliotecas nativas C ou C++ vão para lib/arm64-v8a, lib/armeabi-v7a, lib/x86 e lib/x86_64. Quando você vê um APK com múltiplas abas de arquitetura, significa que o desenvolvedor empacotou bins para todos os tipos de dispositivo compatível. Isso aumenta o tamanho final sem necessariamente melhorar performance.
O arquivo resources.arsc é um arquivo de recursos binários indexados. Ele mapeia identificadores para valores reais. Ferramentas de descompilação usam esse arquivo para reconstruir nomes legíveis dos recursos. Sem ele, você veria apenas números ao invés de strings como bt_ok ou ic_launcher. Existem ainda META-INF com assinaturas digitais, o próprio apk em si (quando há empacotamento aninhado por segurança) e arquivos opcionais como assets que são pastas brut passadas diretamente ao app sem processamento do sistema.
No meu caso, eu precisei extrair um APK de um app interno de logística que tinha um problema específico: um recurso de layout estava sendo carregado de um diretório errado dentro dos assets, mas o identificador no ArSC apontava para o drawable padrão. A interface exibia um botão que na verdade era uma imagem estática. Passei cerca de duas horas comparando os paths no resources.arsc contra os arquivos em res/drawable antes de perceber que o desenvolvedor tinha sobrescrito o recurso original durante uma atualização de sprint. A solução foi extraír o APK, substituir o arquivo drawable pelo correto e reimprimir com keystore de teste. Funcionou, mas demorou mais do que deveria porque a assinatura do APK original era válida e o comando apktool falhava silenciosamente na etapa de rebuild quando os hashes não batiam.
Como extrair o conteúdo na prática
O jeito mais direto é usar o apktool. Ele descompila o APK mantendo a estrutura original e gera arquivos XML legíveis, recursos intactos e o dex separado. Você baixa o jar, coloca junto com o APK que quer analisar e roda: java -jar apktool.jar d arquivo.apk -o pasta_saida
Isso leva entre 10 segundos e 2 minutos dependendo do tamanho do APK e da velocidade do disco. Arquivos grandes com muitos recursos nativos podem levar até 5 minutos em máquinas mais lentas. Para ver o código compilado, você precisa de outra ferramenta. O JADX é bom para iniciantes porque gera Java legível rapidamente. O APKMini ou o CF-Ray são alternativas mais agressivas que tentam reconstruir estruturas originais com variáveis nomeadas, mas dependem muito do nível de ofuscação que o desenvolvedor aplicou. Se o código foi ofuscado com ProGuard ou R8, as classes viram letras minúsculas e os métodos perdem nomes completos. Nesse cenário, o JADX ainda funciona, mas a saída é quase inútil para análise real.
Para inspecionar apenas o manifesto e as permissões sem descompilar tudo, use aapt ou aapt2. Eles são ferramentas de linha de comando embutidas no SDK do Android. Um comando rápido como aapt dump badging arquivo.apk mostra versão, permissões, atividades e serviços em segundos. Gasta menos de 3 segundos e evita carregar interfaces pesadas. Se o objetivo é extrair apenas recursos visuais — ícones, backgrounds, imagens da interface — use o apksigner ou simplesmente renomeie o APK e abra como ZIP. A pasta res/drawable-nome da densidade contém as imagens organizadas por resolução. É comum encontrar PNGs com nome genérico como image_0.png quando o desenvolvedor não fez limpeza durante o build.
Analisar permissões e comportamento
Muita gente para no passo das permissões e acha que entendeu o app inteiro. Não é bem assim. O manifest declara permissões, mas o app pode pedir mais durante a execução via runtime permissions. O Android 13 em diante exige autorização separada para fotos, mídia e notificações. Se o APK foi compilado com compileSdk anterior a 33, essas permissões extras podem não aparecer no manifesto mesmo quando o app as solicita na tela. Para detectar isso, você precisa executar o APK em um emulador ou dispositivo e monitorar as chamadas de runtime. O logcat mostra quando a permissão é solicitada. Um comando simples como adb logcat -s PackageManagerService filtra apenas as linhas relevantes e revela solicitações que não constam no manifesto estático.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Também é importante verificar se o app faz requisições de rede para domínios desconhecidos. Use o mitmproxy ou o Charles Proxy configurados no emulador para capturar tráfego. Apks com certificados pinning vão quebrar nesses proxies, então você precisará usar frida ou objection para contornar a verificação de certificado. Isso é comum em apps bancários e de pagamentos.
Reimprimir um APK modificado
Depois de fazer alterações, você precisa reconstruir e assinar. O apktool cria um novo APK desalinhado na pasta output. Esse APK não é compatível com instalação direta porque falta a assinatura válida. Para corrigir, use o jarsigner ou a ferramenta apksigner do Android SDK. Primeiro gere um keystore temporário se não tiver um pronto:
keytool -genkeypair -v -keystore meusigned.keystore -alias alias_nome -keyalg RSA -keysize 2048 -validity 10000 Depois assine:
apksigner sign --ks meusigned.keystore --ks-key-alias alias_nome --out app_signed.apk app-unaligned.apk O processo leva de 5 a 30 segundos. O erro mais comum é esquecer de alinhar o APK com zipalign antes de assinar. Um APK não alinhado instala, mas roda mais devagar porque o sistema precisa readicionar o alinhamento durante a instalação. O zipalign fica em Android/sdk/build-tools/version/zipalign. Execute zipalign -v -p 4 entrada.apk saída.apk antes de assinar.
Quando eu estava modificando um app de controle de frota para testar uma funcionalidade interna, esqueci o zipalign e levei 40 minutosdebugando porque o app travava apenas em dispositivos com menos de 2GB de RAM. O problema não era código. Era alinhamento de memória. Depois de aplicar o zipalign corretamente, o travamento sumiu em todos os dispositivos de teste.
O que esse tipo de análise NÃO consegue fazer
Extrair um APK não revela lógica de negócio protegida por ofuscação avançada. Bibliotecas nativas compiladas em C++ são praticamente ilegíveis sem reversed engineering dedicado. Recursos embedded em webviews ou carregados dinamicamente via CDN não aparecem no APK. Dados criptografados localmente com chaves geradas em runtime também não são recuperáveis só abrindo o arquivo. Se o app usa Google Play App Signing, você não consegue reinstalar uma versão modificada na conta original do desenvolvedor. A assinatura da Google substitui a sua. Para testes locais, você precisa instalar via adb em conta de desenvolvedor ou usar um dispositivo físico sem vinculação à Play Store.
APKs multi-abas com split configurations também exigem tratamento especial. Um app moderno pode ter um APK base e APKs separados para arquitetura, densidade e idioma. O instalador normal combina tudo automaticamente. Para análise completa, você precisa baixar o app via adb pull ou usar o site apkpure que oferece versões completa sem splits. Ferramentas como o JADX têm limitações conhecidas com código genérico Java e lambda expressions. Métodos lambda aparecem como acessors sintéticos e a reconstrução do fluxo original perde precisão. Em casos assim, extrair o dex bruto e usar o Ghidra ou o radare2 com o plugin androlua dá muito mais controle, mas o tempo de análise pula de minutos para horas.
A maioria dos tutoriais na internet pula essas nuances e mostra apenas o fluxo básico de descompilação e rebuild. Na prática, cada APK traz um conjunto diferente de obstáculos. O que funciona para um app simples de lista de tarefas frequentemente quebra em apps com minificação agressiva, native libraries grandes ou proteção anti-tampering ativada. O essencial é entender a estrutura, saber quais ferramentas correspondem a cada camada e ter paciência para debugar quando algo não compila no rebuild. O resto é tentativa, erro e documentação técnica legida na hora.