Knowledge Center / Mobile runtime attacks / mobile runtime attacks · 2026·01
Accessibility service abuse — automated UI scraping and input synthesis
The Android Accessibility API exists for a real purpose — assistive technology. Once a user grants BIND_ACCESSIBILITY_SERVICE, the granted app receives a stream of every UI event in every other application and can synthesise gestures and key inputs in any of them. The grant is a single click in Settings; no further consent is prompted per use. The abuse pattern follows directly from the platform's design.
1. Mechanism
A foreground app declares an AccessibilityService in its
manifest, requesting BIND_ACCESSIBILITY_SERVICE [1]. The user
must enable the service in Settings → Accessibility → Installed
services. Many malware variants prompt the user with text
designed to look like a routine system or app permission request,
relying on the toggle’s prominent placement and the relative
invisibility of the per-app risk.
Once enabled, the service receives AccessibilityEvent callbacks
[2] for every UI change in every app in the foreground stream:
TYPE_VIEW_CLICKED, TYPE_VIEW_TEXT_CHANGED,
TYPE_WINDOW_CONTENT_CHANGED, TYPE_WINDOW_STATE_CHANGED. The
service can also read the active app’s view tree
(AccessibilityNodeInfo.getRootInActiveWindow()) and perform
actions: dispatchGesture() to draw arbitrary touch trajectories,
performAction() to trigger clicks, long-presses, scroll, and
globalAction() for system-level actions like back and home.
The capability is symmetric — the service both observes and controls the device’s UI as if the user were doing so.
2. Where in the runtime it operates
The service runs as a bound service in its own process, with the
platform’s AccessibilityManagerService (system-server) brokering
events between active services and the foreground UI. The
operating boundary:
- Reads are events delivered to
onAccessibilityEvent()and any explicitgetRootInActiveWindow()calls. - Writes are dispatched through the manager service back to
the target app’s input queue. From the target app’s perspective,
synthesised input arrives via the same input pipeline as user
input — but Android 12 (API 31) added
MotionEvent.FLAG_IS_ACCESSIBILITY_TOOL, which the platform sets on events synthesised by an AccessibilityService; apps that consult this flag can distinguish accessibility-injected events from hardware-driven ones.
Android 13 hardened sideloaded accessibility services [3]:
sideloaded APKs that did not propagate the user-installed-from-
store flag have their accessibility-service toggle gated behind
the AppOps “Restricted setting” gate
(AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS). The user
must perform an explicit “Allow restricted settings” appops
grant from the App Info screen. This narrows but does not
eliminate the surface, because the restriction is user-removable
by deliberate action — not a platform-enforced disabled state.
3. Which checkpoints it bypasses
- Play Integrity / SafetyNet legacy. The device profile is intact, the verdict tier is unchanged, the calling APK is legitimate.
- Hardware attestation. The chain validates; an accessibility service is not a key-provenance issue.
- FIDO2 / passkeys. Pre-Android-14 platform-authenticator
prompts could receive synthesised input from an AccessibilityService,
making it possible to produce an assertion without physical user
interaction. From Android 14, the system Credential Manager and
BiometricPromptsurfaces are rendered in a system-controlled context that does not honour synthesised accessibility input [4]; the protection is architectural (system-rendered surface) rather than a single-flag check. The risk persists on pre-Android-14 builds, on flows that fall back to app-rendered user-verification prompts, or against authenticators that have not adopted the platform-rendered surface. - EMV / 3DS. Same — the cryptogram is authentic for whatever inputs reached the chip.
The platform itself is the attack surface. The checkpoints are oblivious because the attack uses an API that exists on every healthy Android device.
4. Which signals make it observable
runtime.environment. The Trusted Runtime Primitive enumerates
the active accessibility services on the device and signs the
list as part of every Evidence Token at sensitive moments. The
substrate also observes the origin of input events the host app
receives: an event synthesised through dispatchGesture carries
a different platform-level signature than a hardware touch and
can be distinguished by the receiving app when the runtime
exposes that information.
5. Evidence Token shape when observed
The following example is illustrative; field names, type values, and schema are defined in YEI-001 §4 (available through the spec-access process).
{
"ev": [{
"ts": "2026-06-15T10:23:14Z",
"class": "runtime.environment",
"type": "a11y.services_active",
"data": {
"count": 1,
"services": [
{
"package": "com.example.unrecognised",
"service": "com.example.unrecognised.A11yService",
"active_for": "PT4H22M",
"system": false
}
]
}
}]
}
When a sensitive event (login, payment confirm, key-rotation) fires while a non-system, third-party accessibility service is active, Execution Evidence Infrastructure (EEI) — the device-identity infrastructure layer for banking and payments — shows the operator the signed list and the operator decides accordingly.
6. Cross-references
- Sibling articles:
overlay-injection,malicious-ime,malware-asia-africa - Architecture:
/architecture/runtime-coherence,/architecture/threat-model - Glossary:
/glossary— runtime.environment
7. External references
[1] Android Developers. AccessibilityService API. developer.android.com/reference/android/accessibilityservice/AccessibilityService. Cited 2026-01-05.
[2] Android Developers. AccessibilityEvent. developer.android.com/reference/android/view/accessibility/AccessibilityEvent. Cited 2026-01-05.
[3] Android Developers. Android 13 — Restricted settings for sideloaded apps (OPSTR_ACCESS_RESTRICTED_SETTINGS). developer.android.com/about/versions/13/features#restricted-settings. Cited 2026-01-05.
[4] Android Developers. Android 14 — Behavior changes: Credential Manager and BiometricPrompt system-rendered surfaces. developer.android.com/about/versions/14/behavior-changes-all. Cited 2026-01-05.