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をサポートする

概要

AccessibilityService は障害のあるユーザが Android デバイスとやり取りするのを支援するために作られました。残念ながら、同じく強力な automation APIs(グローバルナビゲーション、テキスト入力、ジェスチャー dispatch、オーバーレイウィンドウ…)はマルウェアによって武器化され、ハンドセットを完全にリモートで制御するために利用され得ます without root privileges

近年の Android 銀行型 Trojans および Remote-Access-Trojans (RATs)(例:PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda など多く)は、同じレシピに従います:

  1. 被害者にソーシャルエンジニアリングを仕掛け、悪意のある accessibility service を有効化させる(BIND_ACCESSIBILITY_SERVICE permission は「high-risk」と見なされ、明示的なユーザ操作が必要です)。
  2. サービスを利用して
  • 画面に表示されるすべての UI イベントとテキストをキャプチャする、
  • 合成ジェスチャー(dispatchGesture)やグローバルアクション(performGlobalAction)を注入して、オペレータが望む任意のタスクを自動化する、
  • 正当なアプリの上に全画面オーバーレイを描画する(TYPE_ACCESSIBILITY_OVERLAY ウィンドウタイプを使用、SYSTEM_ALERT_WINDOW のプロンプトは不要!)、
  • システムダイアログ上のボタンを被害者の代わりにクリックして追加のランタイム権限を静かに付与する。
  1. データを流出させたり、ユーザが普通の画面を見ている間にリアルタイムでOn-Device-Fraud (ODF) を実行する。

Packed Accessibility droppers

ClayRat v3.0.8 はその Accessibility RAT を staged payload と組み合わせ、assets/ の下に隠しています。ランタイムでホスト APK は:

  1. assets/*.dat から暗号化された blob をストリーミングする。
  2. Java/Kotlin ローダ内に埋め込まれたハードコードされた AES/CBC キー+IV で復号する。
  3. 平文の 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 module を off-disk に保持し、ユーザーが危険な権限をすでに付与するまで 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自動化のプリミティブ

アクセシビリティサービス自動化のスケルトン ```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>

これら2つの APIs だけで攻撃者は次のことができる:
* 画面のロックを解除し、銀行アプリを開き、その UI ツリーをナビゲートして送金フォームを送信する。
* 表示されるすべての permission ダイアログを承認する。
* Play Store intent 経由で追加の APKs をインストール/更新する。

---

## 悪用パターン

### 1. Overlay Phishing (Credential Harvesting)
透明または不透明な `WebView` が 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);

被害者が偽フォームに資格情報を入力している間、バックグラウンドのアプリが同じジェスチャーを受け取る — 「draw over other apps」のような怪しいプロンプトは一切表示されない。

詳細な例: Accessibility Overlay Phishing セクション (Tapjacking ページ内)。

ClayRat はこの機能を show_block_screen / hide_block_screen コマンドで公開しており、これらは C2 からオーバーレイテンプレートをダウンロードする。オペレータはレイアウトを動的に切り替えて次を実行できる:

  • 黒く覆う パネルを表示して被害者に端末がオフまたはフリーズしていると誤認させ、その間にバックグラウンドの自動ジェスチャーで Play Protect を無効化したり追加の権限を付与したりする。
  • システム更新 / バッテリー最適化 の偽パネルを表示してデバイスが「処理中」であることを正当化し、バックグラウンドの自動化を継続する。
  • インタラクティブな PIN パッド オーバーレイを表示してシステムのロック画面を模倣する — マルウェアは各桁を記録し、4桁コードが入力されると直ちにオペレータへストリーム送信する。

TYPE_ACCESSIBILITY_OVERLAY ウィンドウは SYSTEM_ALERT_WINDOW 権限プロンプトを発生させないため、被害者にはデコイ UI だけが見える一方で RAT は下層の実アプリと継続的にやり取りを行う。

2. デバイス上での不正取引自動化

PlayPraetor のようなマルウェアファミリは、オペレータが高レベルコマンド(init, update, alert_arr, report_list, …)を発行できる持続的な WebSocket チャネルを維持する。サービスはそれらのコマンドを上記の低レベルジェスチャに変換し、該当デバイスに紐づく多要素認証を容易に回避してリアルタイムの不正取引を実行する。

3. 画面ストリーミングと監視

ClayRat は通常の MediaProjection 手法をリモートデスクトップスタックへ拡張する:

  1. turbo_screen が MediaProjection の同意ダイアログを起動する;Accessibility サービスが “Start now” をクリックするため被害者は介入しない。
  2. 取得した MediaProjection トークンで ImageReader をバックエンドに持つ VirtualDisplay を作成し、ForegroundService を維持してワーカースレッドでフレームをドレインする。
  3. フレームはオペレータ提供の set_quality パラメータに従って JPEG/PNG エンコードされ(欠如時はデフォルト 60)、カスタム ClayRemoteDesktop user-agent を宣伝する HTTP→WebSocket アップグレード経由で送信される。
  4. start_desktop / stop_desktop がキャプチャスレッドを管理し、screen_tap, screen_swipe, input_text, press_home, press_back, press_recents がライブフレームバッファに対してジェスチャをリプレイする。

その結果、root やカーネルエクスプロイトを使わずに正式な API だけで配信される VNC 風のフィードを実現し、ミリ秒単位の遅延で攻撃者にライブの状況認識を提供する。

4. ロック画面の認証情報窃取と自動解除

ClayRat は com.android.systemui (Keyguard) が発する TYPE_WINDOW_CONTENT_CHANGED / TYPE_VIEW_TEXT_CHANGED イベントを購読し、稼働中のガードを再構築する:

  • PIN – ロッカーが完了を報告するまでテンキーのボタン押下を監視する。
  • Password – 各 AccessibilityEvent でフォーカスされたパスワードフィールドに現れた文字列を連結する。
  • Pattern – 3×3 グリッド上のジェスチャ座標から推定される順序付きノードインデックスを記録する。

シークレットとメタデータ(ロック種別 + タイムスタンプ)は lock_password_storage の下で SharedPreferences にシリアライズされる。オペレータが auto_unlock を送ると、サービスは unlock_device / screen_on でデバイスを起動し、保存された桁やジェスチャを dispatchGesture 経由で再生してサイレントに keyguard をバイパスし、その後の ODF ワークフローを継続させる。

5. 通知を使ったフィッシングと収集

付随する Notification Listener は通知シェードをフィッシング面に変える:

  • get_push_notifications は表示中の全通知をダンプする(OTP / MFA メッセージを含む)。
  • notifications コマンドは notifications_enabled フラグを切り替え、以降の onNotificationPosted() ペイロードをリアルタイムで C2 にストリームする。
  • send_push_notification によりオペレータは銀行アプリやチャットアプリを装った偽のインタラクティブ通知を作成でき、被害者が入力したテキストは資格情報として解析され即座に外部へ流出する。

Accessibility により通知シェードをプログラム的に開閉できるため、この手法は対象アプリに触れることなくシークレットを収集する。

6. 電話と SMS を使ったコマンドチャネル

被害者を強引に RAT をデフォルトの SMS アプリに設定させた後、以下のコマンドでモデムを完全制御できる:

  • send_smsretransmishion は任意またはリプレイしたメッセージを攻撃者管理の番号へ送信する。
  • messsms は連絡先データベース全体を反復してフィッシングリンクをスパム送信し、ワームのように拡散させる。
  • make_call はソーシャルエンジニアリング用途の音声通話を開始する。
  • get_sms_list / get_smsget_call_log / get_calls は受信箱や通話履歴をダンプし、MFA コードや通話メタデータを即時に悪用できるようにする。

Accessibility 駆動の UI ナビゲーションと組み合わせることで、ClayRat は通知/SMS 経由で OTP を受信して即座に対象の銀行やエンタープライズアプリ内に入力することができる。

7. 発見、収集、プロキシ

追加の ClayRat コマンドは環境をマッピングし、C2 のレジリエンスを保つ:

  • get_apps / get_apps_list はインストール済みパッケージを列挙する (ATT&CK T1418)。
  • get_device_info はモデル、OS バージョン、バッテリ状態を報告する (T1426)。
  • get_cam / get_camera はフロントカメラの静止画を取得し、get_keylogger_data はロック PIN やパスワード、敏感フィールドからスクレイピングしたビュー説明やヒントをシリアライズする。
  • get_proxy_data はプロキシ WebSocket URL を取得し、ユニークデバイス ID を付加してジョブを起動し、同じ双方向チャネル上で HTTP/HTTPS をトンネルする (T1481.002 / T1646)。

PlayPraetor – command & control workflow

  1. HTTP(S) heartbeat – ハードコーディングされたリストを順に試し、どれかが POST /app/searchPackageName にアクティブな C2 を返すまで反復する。
  2. WebSocket (port 8282) – 双方向 JSON コマンド:
  • update – 新しい conf/APK をプッシュ
  • alert_arr – オーバーレイテンプレートを構成
  • report_list – ターゲットパッケージ名のリストを送信
  • heartbeat_web – キープアライブ
  1. RTMP (port 1935) – ライブ画面 / ビデオストリーミング。
  2. REST exfiltration
  • /app/saveDevice (fingerprint)
  • /app/saveContacts | /app/saveSms | /app/uploadImageBase64
  • /app/saveCardPwd (bank creds)

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+) を強制してサイドロードされたサービスをブロックできる。
  • 実行中のサービスを解析:
adb shell dumpsys accessibility | grep "Accessibility Service"

Hardening recommendations for app developers

  • 敏感なビューに android:accessibilityDataSensitive="accessibilityDataPrivateYes" をマークする (API 34+)。
  • tap/overlay ハイジャックを防ぐために setFilterTouchesWhenObscured(true)FLAG_SECURE を組み合わせる。
  • WindowManager.getDefaultDisplay().getFlags()ViewRootImpl API をポーリングしてオーバーレイを検出する。
  • Settings.canDrawOverlays() が有効、または信頼されていない Accessibility サービスがアクティブな場合は動作を拒否する。

ATS automation cheat-sheet (Accessibility-driven)

Malware は Accessibility API のみで銀行アプリを完全自動化できる。汎用プリミティブ:

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

Example flow (チェコ語 → 英語ラベル):

  • “Nová platba” (新しい支払い) → クリック
  • “Zadat platbu” (支払いを入力) → クリック
  • “Nový příjemce” (新しい受取人) → クリック
  • “Domácí číslo účtu” (国内の口座番号) → フォーカスして ACTION_SET_TEXT
  • “Další” (次へ) → クリック → … “Zaplatit” (支払う) → クリック → PINを入力

Fallback: カスタムウィジェットのためにテキスト検索が失敗した場合、dispatchGesture を使ったハードコードされた座標。

Also seen: limits UI に移動して振込前に日次限度を増やすことで、check_limitlimit への事前ステップを実行する例。

テキストベースの擬似スクリーンストリーミング

低遅延のリモート制御のために、フル動画ストリーミングの代わりに現在の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);

注: これらのポリシーの正確な可用性は Android のバージョンや OEM により異なります。テスト中はデバイスのポリシー役割(admin vs owner)を確認してください。

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 モジュールは、サードステージとして専用の NFC-relay アプリ(例: NFSkate)をインストールおよび起動し、被害者をカード呈示によるリレー手順へ導く overlay ガイドを注入することさえあります。

Background and TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay


References

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をサポートする