Wykorzystywanie AccessibilityService w Androidzie

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Przegląd

AccessibilityService zostało stworzone, aby pomóc użytkownikom z niepełnosprawnościami w interakcji z urządzeniami z Androidem. Niestety te same powerful automation APIs (global navigation, text input, gesture dispatch, overlay windows…) mogą być weaponised przez malware, by uzyskać pełną zdalną kontrolę nad urządzeniem bez uprawnień roota.

Współczesne Android banking Trojans i Remote-Access-Trojans (RATs) takie jak PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda i wiele innych stosują ten sam scenariusz:

  1. Nakłonić ofiarę metodami socjotechnicznymi do włączenia złośliwej accessibility service (uprawnienie BIND_ACCESSIBILITY_SERVICE jest uznawane za “high-risk” i wymaga wyraźnej akcji użytkownika).
  2. Wykorzystać usługę do
  • przechwycenia każdego zdarzenia UI i tekstu pojawiającego się na ekranie,
  • wstrzykiwania syntetycznych gestów (dispatchGesture) i globalnych akcji (performGlobalAction) w celu automatyzacji dowolnego zadania operatora,
  • rysowania nakładek na pełnym ekranie ponad legitnymi aplikacjami przy użyciu typu okna TYPE_ACCESSIBILITY_OVERLAY (bez monitu SYSTEM_ALERT_WINDOW!),
  • potajemnego przyznawania dodatkowych runtime permissions poprzez klikanie w systemowe dialogi w imieniu ofiary.
  1. Exfiltrate data lub przeprowadzenia On-Device-Fraud (ODF) w czasie rzeczywistym, podczas gdy użytkownik patrzy na zupełnie normalny ekran.

Packed Accessibility droppers

ClayRat v3.0.8 łączy swój Accessibility RAT z etapowanym payloadem ukrytym w assets/. W czasie wykonywania hostujący APK:

  1. Strumieniuje zaszyfrowany blob z assets/*.dat.
  2. Deszyfruje go za pomocą hard-coded AES/CBC key + IV osadzonego w loaderze Java/Kotlin.
  3. Zapisuje plaintext DEX w prywatnym katalogu aplikacji i ładuje go przez DexClassLoader, ujawniając rzeczywiste klasy spyware tylko w pamięci.
byte[] blob = readAsset("payload.enc");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec key = new SecretKeySpec(hex("A1..."), "AES");
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] dex = c.doFinal(blob);
DexClassLoader cl = new DexClassLoader(writeTemp(dex), getCodeCacheDir().getPath(), null, getClassLoader());
cl.loadClass("com.clayrat.Core").newInstance();

Ten wzorzec pakowania (ATT&CK T1406.002) utrzymuje moduł Accessibility poza dyskiem aż do momentu wykonania droppera, omijając skanowanie statyczne sygnatur i Play Protect, dopóki użytkownik nie przyzna niebezpiecznych uprawnień.


Żądanie uprawnienia

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

Plik XML towarzyszący definiuje, jak będzie wyglądać fałszywe okno dialogowe:

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

Zdalne prymitywy automatyzacji UI

Szkielet automatyzacji usługi Accessibility ```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); } }

</details>

Przy użyciu tylko tych dwóch API atakujący może:
* Odblokować ekran, otworzyć aplikację bankową, przejść po jej drzewie UI i wysłać formularz przelewu.
* Zaakceptować każde pojawiające się okno dialogowe z uprawnieniami.
* Zainstalować/aktualizować dodatkowe APK za pomocą Play Store intent.

---

## Wzorce nadużyć

### 1. Overlay Phishing (Credential Harvesting)
Do menedżera okien dodawany jest przezroczysty lub nieprzezroczysty `WebView`:
```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);

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.

Szczegółowy przykład: sekcja Accessibility Overlay Phishing na stronie Tapjacking.

ClayRat exposes this capability with the show_block_screen / hide_block_screen commands that download overlay templates from the C2. Operators can switch layouts on the fly to:

  • Zaciemnij panel tak, by ofiara uznała, że telefon jest wyłączony lub zablokowany, podczas gdy zautomatyzowane gesty wyłączają Play Protect lub przyznają dodatkowe uprawnienia.
  • Wyświetl fałszywe panele system update / battery optimization, które uzasadniają dlaczego urządzenie jest „zajęte”, podczas gdy automatyzacja w tle nadal działa.
  • Pokaż interaktywną klawiaturę PIN jako overlay, która odzwierciedla systemowy ekran blokady — malware przechwytuje każdą cyfrę i przesyła ją operatorowi zaraz po wpisaniu 4‑cyfrowego kodu.

Because TYPE_ACCESSIBILITY_OVERLAY windows never raise the SYSTEM_ALERT_WINDOW permission prompt, the victim only sees the decoy UI while the RAT keeps interacting with the real apps underneath.

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

ClayRat upgrades the usual MediaProjection trick into a remote desktop stack:

  1. turbo_screen triggers the MediaProjection consent dialog; the Accessibility service clicks “Start now” so the victim never intervenes.
  2. With the resulting MediaProjection token it creates a VirtualDisplay backed by an ImageReader, keeps a ForegroundService alive, and drains frames on worker threads.
  3. Frames are JPEG/PNG encoded according to the operator-supplied set_quality parameter (defaults to 60 when missing) and shipped over an HTTP→WebSocket upgrade advertising the custom ClayRemoteDesktop user-agent.
  4. start_desktop / stop_desktop manage the capture threads while screen_tap, screen_swipe, input_text, press_home, press_back and press_recents replay gestures against the live framebuffer.

The result is a VNC-like feed delivered entirely through sanctioned APIs—no root or kernel exploits—yet it hands the attacker live situational awareness with millisecond latency.

4. Lock-screen credential theft & auto-unlock

ClayRat subscribes to TYPE_WINDOW_CONTENT_CHANGED / TYPE_VIEW_TEXT_CHANGED events emitted by com.android.systemui (Keyguard). It reconstructs whatever guard is active:

  • PIN – obserwuje naciśnięcia klawiszy na klawiaturze numerycznej aż locker zgłosi ukończenie.
  • Password – konkatenacja ciągów widocznych w focusowanym polu hasła dla każdego AccessibilityEvent.
  • Pattern – rejestruje uporządkowane indeksy węzłów wywnioskowane z współrzędnych gestów na siatce 3×3.

Sekrety wraz z metadanymi (typ blokady + znacznik czasu) są serializowane do SharedPreferences pod lock_password_storage. Kiedy operator wysyła auto_unlock, serwis wybudza urządzenie za pomocą unlock_device / screen_on, odtwarza zapisane cyfry lub gesty przez dispatchGesture i cicho obejmuje keyguard, by kolejne workflow ODF mogły kontynuować.

5. Notification phishing & harvesting

A companion Notification Listener turns the shade into a phishing surface:

  • get_push_notifications zrzuca wszystkie aktualnie widoczne powiadomienia, włącznie z wiadomościami OTP / MFA.
  • Komenda notifications przełącza flagę notifications_enabled tak, że każdy przyszły payload z onNotificationPosted() jest strumieniowany do C2 w czasie rzeczywistym.
  • send_push_notification pozwala operatorom tworzyć fałszywe, interaktywne powiadomienia podszywające się pod banki lub aplikacje czatu; każdy tekst wpisany przez ofiarę jest parsowany jako poświadczenia i natychmiast eksfiltrowany.

Because Accessibility can open/dismiss the notification shade programmatically, this method harvests secrets without touching the targeted apps.

6. Telephony & SMS command channel

After coercing the user into setting the RAT as the default SMS app, the following commands provide complete modem control:

  • send_sms and retransmishion wysyłają dowolne lub odtworzone wiadomości na numery kontrolowane przez atakującego.
  • messsms iteruje przez całą bazę kontaktów, aby rozsyłać phishingowe linki w celu pasożytniczego rozprzestrzeniania.
  • make_call inicjuje połączenia głosowe wspierające scenariusze social-engineeringowe.
  • get_sms_list / get_sms i get_call_log / get_calls zrzucają skrzynki odbiorcze i historię połączeń, dzięki czemu kody MFA lub metadane połączeń mogą być natychmiast nadużyte.

W połączeniu z nawigacją UI sterowaną przez Accessibility, ClayRat może otrzymać OTP przez powiadomienie/SMS i natychmiast go wpisać wewnątrz docelowej aplikacji bankowej lub korporacyjnej.

7. Discovery, collection & proxying

Additional ClayRat commands map the environment and keep C2 resilient:

  • get_apps / get_apps_list enumerują zainstalowane pakiety (ATT&CK T1418).
  • get_device_info raportuje model, wersję OS i stan baterii (T1426).
  • get_cam / get_camera robią zdjęcia przednią kamerą, podczas gdy get_keylogger_data serializuje PINy blokady oraz hasła, opisy widoków i podpowiedzi zdrapane z wrażliwych pól.
  • get_proxy_data pobiera adres proxy WebSocket, dopisuje unikalne ID urządzenia i uruchamia zadanie, które tuneluje HTTP/HTTPS przez ten sam dwukierunkowy kanał (T1481.002 / T1646).

PlayPraetor – command & control workflow

  1. HTTP(S) heartbeat – iteracja po hard-coded liście aż jedna domena odpowie POST /app/searchPackageName z aktywnym C2.
  2. WebSocket (port 8282) – dwukierunkowe komendy JSON:
  • update – wypchnięcie nowej konf/APKów
  • alert_arr – konfiguracja szablonów overlay
  • report_list – wysłanie listy docelowych package names
  • heartbeat_web – keep-alive
  1. RTMP (port 1935) – live streaming ekranu/wideo.
  2. 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 – szukaj aplikacji, które nie pochodzą z 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:

Metody pomocnicze do automatyzacji ATS ```java // Helpers inside your AccessibilityService private List 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); } ```

Przykładowy przebieg (czeski → angielskie etykiety):

  • “Nová platba” (Nowa płatność) → kliknij
  • “Zadat platbu” (Wprowadź płatność) → kliknij
  • “Nový příjemce” (Nowy odbiorca) → kliknij
  • “Domácí číslo účtu” (Krajowy numer konta) → ustaw fokus i ACTION_SET_TEXT
  • “Další” (Dalej) → kliknij → … “Zaplatit” (Zapłać) → kliknij → wprowadź PIN

Fallback: hard-coded współrzędne z dispatchGesture gdy wyszukiwanie tekstu zawiedzie z powodu niestandardowych widgetów.

Zaobserwowano również wstępne kroki do check_limit i limit, polegające na przejściu do interfejsu limits UI i zwiększeniu dziennych limitów przed transferem.

Pseudo-strumieniowanie ekranu oparte na tekście

Do zdalnego sterowania o niskim opóźnieniu, zamiast pełnego strumieniowania wideo, zrzucaj tekstową reprezentację bieżącego drzewa UI i wysyłaj ją wielokrotnie do 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);
}

To stanowi podstawę dla poleceń takich jak txt_screen (jednorazowe) i screen_live (ciągłe).

Primitwy przymuszania Device Admin

Gdy Device Admin receiver zostanie aktywowany, te wywołania zwiększają możliwości przechwytywania poświadczeń i utrzymania kontroli:

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

Uwaga: dokładna dostępność tych polityk różni się w zależności od wersji Androida i OEM; zweryfikuj rolę polityki urządzenia (admin vs owner) podczas testów.

Wzorce ekstrakcji seed-phrase portfeli Crypto

Zaobserwowane przepływy dla MetaMask, Trust Wallet, Blockchain.com i Phantom:

  • Unlock with stolen PIN (captured via overlay/Accessibility) or provided wallet password.
  • Przejdź: Settings → Security/Recovery → Reveal/Show recovery phrase.
  • Zbieraj frazę poprzez keylogging text nodes, secure-screen bypass lub screenshot OCR, gdy tekst jest zasłonięty.
  • Obsługa wielu lokalizacji (EN/RU/CZ/SK) w celu stabilizacji selektorów — preferuj viewIdResourceName jeśli dostępne, w przeciwnym razie zastosuj wielojęzyczne dopasowanie tekstu.

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.

Tło i TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay


Odniesienia

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks