componentes-android.md — manifest, permissões, componentes e assinatura
Fontes: extraido/AndroidManifest.xml (binário), decompilado/apktool/AndroidManifest.xml (decodificado),
evidencias/rea-inspect-android-package.json (REA/jadx), evidencias/apksigner-verify.txt.
1. Cabeçalho do manifest
<manifest package="com.banking.trackerpro"
android:versionCode="431870" android:versionName="7.28.82"
android:compileSdkVersion="34" platformBuildVersionCode="34">
<application android:label="@string/app_name" <!-- "Nfc Security" -->
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/Theme.NovoNome"
android:appComponentFactory="androidx.core.app.CoreComponentFactory"
android:extractNativeLibs="false" />
Observações relevantes:
- allowBackup=false + regras de extração → reduz aquisição forense de dados locais (pouco a extrair de qualquer forma).
- networkSecurityConfig proíbe HTTP claro e não define pinning → o wss:///https:// é protegido por TLS de sistema.
- Theme.NovoNome e appComponentFactory de AndroidX são herança do template.
2. Permissões (4 declaradas + 1 definida)
| Permissão | Tipo | Leitura |
|---|---|---|
android.permission.INTERNET |
uses-permission | necessária ao relay (WebSocket) |
android.permission.NFC |
uses-permission | central: ler o chip do cartão |
android.permission.FOREGROUND_SERVICE |
uses-permission | declarada mas não usada — não há <service> no manifest (resíduo) |
app.nfcsecurity.vault.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION |
uses + <permission protectionLevel="signature"> |
gerada pelo AGP (AndroidX); não é indicador de comportamento |
android.hardware.nfc (required="true") |
uses-feature | o app só instala em aparelho com NFC — pré-requisito do relay |
Ausência notável: nenhuma permissão de localização, câmera, SMS, contatos, armazenamento ou acessibilidade. O objetivo não é coletar do dispositivo: é usar o cartão e o PIN.
3. Componentes declarados
| Componente | Classe | Exportado | Filtros | Evidência / papel |
|---|---|---|---|---|
| Activity | app.nfcsecurity.vault.ReFragment |
true (exported="true", launchMode="singleTask") |
MAIN+LAUNCHER; android.nfc.action.TECH_DISCOVERED + meta-data @xml/nfc_tech_filter |
entrypoint real. É uma AppCompatActivity chamada "Fragment" (nome enganoso). Recebe a tag NFC também com o app já aberto (onNewIntent) |
| Activity | app.nfcsecurity.vault.MainActivity |
false | nenhum | tela alternativa de status do cartão; nenhum código a inicia (não há startActivity para ela) → código morto nesta build |
| Provider | androidx.startup.InitializationProvider |
false | — | authorities="com.banking.trackerpro.androidx-startup" (inicialização de Emoji2, ProcessLifecycle, ProfileInstaller) |
| Receiver | androidx.profileinstaller.ProfileInstallReceiver |
true, protegido por android.permission.DUMP |
4 actions androidx.profileinstaller.* |
biblioteca AndroidX; exploração exige DUMP (assinatura/shell) → não é superfície prática |
Não há: <service>, <activity-alias>, outros providers, widgets, ou android:permission protegendo o app.
4. Intent filters e deep links
MAIN/LAUNCHER→ ícone na gaveta.android.nfc.action.TECH_DISCOVEREDcom@xml/nfc_tech_filter: trêstech-list(IsoDep,NfcA,NfcB) → o app se registra para QUALQUER cartão/tag ISO-DEP aproximado, não apenas AIDs específicos, enquanto está em primeiro plano (enableForegroundDispatchemonResume,ReFragment.java:346-353).- Não existem deep links (
VIEW+BROWSABLE+http/https) — confirmado no manifest decodificado e no inventário do REA (actionsdas activities: apenas MAIN e TECH_DISCOVERED). Consequência: não é possível "abrir" o app por URL; o gatilho é físico (NFC) ou o launcher.
5. Superfície de ataque do próprio app (para o dispositivo do usuário)
| Item | Evidência | Risco |
|---|---|---|
WebView com setJavaScriptEnabled(true) e addJavascriptInterface(...,"Android") |
ReFragment.java:139-145 |
ponte nativa exposta a qualquer página carregada na WebView |
setAllowFileAccess(true) / setAllowContentAccess(true) |
ReFragment.java:141-142 |
a página remota pode tentar ler file:///content:// |
WebViewClient que não valida host antes de carregar (handleUrl só checa presença de ?token=) |
bd.java:handleUrl |
qualquer URL do servidor é carregada; ?token= força reload |
JS injetado a cada onPageFinished com setInterval(...,1000) enviando location.href ao nativo |
bd.java:injectJavascript |
keylogging de URL contínuo (inclui pin=) |
Settings.Secure android_id usado para compor o session_id |
ReFragment.java:299-314 |
identificador do aparelho enviado ao servidor (MODEL_last4(android_id)) |
6. Assinatura (evidência inspect-apk-signature do REA + apksigner verify)
| Item | Valor |
|---|---|
| Esquemas | v1 presente (META-INF/ANDROID.SF + ANDROID.RSA), v2 presente, v3 presente; v3.1 e v4 ausentes |
apksigner verify |
Verifies — v2=true, v3=true; v1=false (não exigido com minSdk 24) |
| Signers | 1 |
| Certificado | C=BR, ST=SP, L=City, O=Local, OU=Mobile, CN=Android — autoassinado (issuer == subject) |
| SHA-256 do certificado | 06c08cb7e562e94f3e3a07325f26d47f4de3ffc08b6b1725f01c799deb227fdc |
| SHA-1 | 0a7045801ffb45867ab7ae26b6b5e7bdf2ada40f |
| Chave / algoritmo | RSA 2048 · assinatura sha256WithRSAEncryption (OID 1.2.840.113549.1.1.1) |
| Serial | B097A580D675E806 |
| Validade | 2026-10-30T16:20:46Z → 2054-03-17T16:20:46Z |
| Digest v2 do APK | sha256 declarado 3254962c…704e, confere com o conteúdo (matches_apk: true) |
Interpretação (com o cuidado devido):
- Fato observado: certificado autoassinado com dados genéricos (O=Local, L=City, CN=Android) — não é uma chave de
distribuidor conhecido nem de loja; típico de build privada/reassinada.
- Fato observado: notBefore do certificado é 2026-10-30 16:20:46 UTC, enquanto as entradas ZIP datam de
2026-10-21 15:10.
- Hipótese: o APK foi assinado (ou re-assinado) com uma chave gerada no mesmo dia da entrega, depois de ter sido
montado — padrão de pipeline de distribuição de amostras, não de app publicado em loja.
- Não verificado: autenticidade, lineage de rotação, cobertura de entradas v1 (o REA registra explicitamente que
igualdade de digest não é verificação criptográfica de assinatura).