Runtime Permission Manipulation¶
Granting permissions without user interaction. Once malware obtains BIND_ACCESSIBILITY_SERVICE, it can navigate Settings screens, tap "Allow" buttons, and toggle switches to escalate from a single permission to full device control. Every modern Android banking trojan uses some variant of this technique.
Requirements
| Requirement | Details |
|---|---|
| Permission | BIND_ACCESSIBILITY_SERVICE (user must enable manually) |
| Trigger | Initial social engineering to enable accessibility |
The only user interaction needed is enabling the accessibility service. Everything after that is automated.
Accessibility-Based Auto-Grant¶
The core technique: the malware's accessibility service programmatically navigates system Settings and interacts with UI elements to grant itself additional permissions.
View Tree Navigation¶
The accessibility service calls getRootInActiveWindow() to obtain the root AccessibilityNodeInfo of the current screen, then traverses the view tree searching for specific text labels or resource IDs matching permission toggles.
AccessibilityNodeInfo root = getRootInActiveWindow();
List<AccessibilityNodeInfo> nodes = root.findAccessibilityNodeInfosByText("Allow");
for (AccessibilityNodeInfo node : nodes) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
Settings Navigation Flow¶
The malware opens specific Settings screens via intents, then uses accessibility to manipulate them:
| Permission Target | Intent Action | UI Interaction |
|---|---|---|
Overlay (SYSTEM_ALERT_WINDOW) |
Settings.ACTION_MANAGE_OVERLAY_PERMISSION |
Toggle switch to ON |
| Install unknown apps | Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES |
Toggle switch to ON |
| Notification access | Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS |
Toggle switch to ON |
| Battery optimization | Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS |
Select app, tap "Allow" |
| Default SMS app | Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT |
Select malware app |
| Device admin | Settings.ACTION_ADD_DEVICE_ADMIN |
Tap "Activate" |
Runtime Permission Dialogs¶
For standard runtime permissions (camera, contacts, location, SMS), the malware triggers the system permission dialog and immediately clicks "Allow" via accessibility before the user can react.
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getPackageName().equals("com.google.android.packageinstaller") ||
event.getPackageName().equals("com.android.permissioncontroller")) {
AccessibilityNodeInfo root = getRootInActiveWindow();
List<AccessibilityNodeInfo> allowButtons =
root.findAccessibilityNodeInfosByViewId(
"com.android.permissioncontroller:id/permission_allow_button");
if (!allowButtons.isEmpty()) {
allowButtons.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
The malware monitors for the com.android.permissioncontroller package in TYPE_WINDOW_STATE_CHANGED events, then locates and clicks the "Allow" button. On some Android versions, the button IDs differ (permission_allow_foreground_only_button, permission_allow_always_button), so families like ERMAC and Hook enumerate multiple possible IDs.
Default SMS App Exploitation¶
Android grants READ_SMS, RECEIVE_SMS, SEND_SMS, and RECEIVE_MMS automatically to whichever app the user designates as the default SMS handler. Malware exploits this by requesting default SMS status:
- Launch
Telephony.Sms.Intents.ACTION_CHANGE_DEFAULTwith its own package - Use accessibility to tap "Yes" on the confirmation dialog
- Receive all SMS permissions automatically without individual grants
- Intercept OTPs and bank verification codes
- Optionally revert to the original SMS app after capturing needed data
Families including Cerberus, Anubis, and FluBot use this approach to gain SMS access without triggering individual permission prompts.
Session-Based Installer Bypass (Android 13+)¶
Android 13 introduced "Restricted Settings" to block sideloaded apps from enabling accessibility services and notification listeners. Apps installed via ACTION_VIEW (the standard sideload path) are flagged as restricted. However, apps installed via PackageInstaller session-based API are treated as marketplace-installed and exempt.
How Droppers Exploit This¶
The dropper app uses the session-based installation API to install its payload, mimicking how legitimate app stores install apps:
PackageInstaller installer = getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params =
new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_SET_INSTALL);
int sessionId = installer.createSession(params);
PackageInstaller.Session session = installer.openSession(sessionId);
OutputStream out = session.openWrite("payload", 0, -1);
InputStream in = getAssets().open("payload.apk");
byte[] buffer = new byte[65536];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
session.fsync(out);
out.close();
Intent intent = new Intent(this, InstallReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(this, sessionId, intent,
PendingIntent.FLAG_MUTABLE);
session.commit(pending.getIntentSender());
The OS cannot distinguish between a dropper using this API and a legitimate marketplace. The payload installs without the "Restricted Settings" flag, and the user can enable accessibility services normally.
Notable Droppers¶
ThreatFabric documented SecuriDropper in October 2023 as the first dropper-as-a-service using this technique. Since then, it has become standard practice across the MaaS ecosystem.
| Dropper / Family | Year | Notes |
|---|---|---|
| BugDrop | 2022 | Early proof-of-concept before Android 13 release |
| SecuriDropper | 2023 | First DaaS offering session-based bypass |
| SpyNote | 2024 | Adopted session-based installation for accessibility bypass |
| Anatsa | 2024 | Play Store droppers with session-based payload delivery |
| Medusa | 2024 | Updated dropper chain using session-based install |
Android 14 and 15
Android 14 did not fix this bypass. The same session-based technique works. Android 15 expanded restricted settings enforcement but still struggles to differentiate legitimate session-based installs from malicious ones.
Biometric Downgrade to PIN¶
Chameleon introduced a technique in late 2023 to force the device from biometric authentication to PIN entry. The C2 sends an interrupt_biometric command, and the malware uses accessibility to:
- Navigate to Settings > Security > Biometric
- Disable fingerprint and face unlock
- Force the device to fall back to PIN/password authentication
- Capture the PIN via keylogging when the user next unlocks
This works because disabling biometrics is a Settings toggle, accessible via the same accessibility-based UI manipulation used for permission grants. See also: Fake Biometric Prompts for overlay-based PIN capture.
Family Comparison¶
| Family | Auto-Grant | SMS Takeover | Session Install | Biometric Downgrade | Restricted Settings Bypass |
|---|---|---|---|---|---|
| Cerberus | Yes | Yes (default SMS) | No (pre-dates it) | No | N/A |
| ERMAC | Yes | Via accessibility | No | No | Via dropper |
| Hook | Yes | Via accessibility | Yes | No | Yes |
| Medusa | Yes | Broadcast receiver | Yes | No | Yes |
| Anatsa | Yes | No (ATS-focused) | Yes | No | Yes |
| Xenomorph | Yes | Via accessibility | No | No | Via dropper |
| Chameleon | Yes | No | Yes (Zombinder) | Yes | Yes |
| SpyNote | Yes | Via accessibility | Yes | No | Yes |
Android Version Timeline¶
| Version | Change | Malware Adaptation |
|---|---|---|
| Android 6 | Runtime permissions introduced | Malware auto-clicks "Allow" via accessibility |
| Android 8 | TYPE_APPLICATION_OVERLAY replaces TYPE_SYSTEM_ALERT |
Accessibility grants the new overlay permission |
| Android 10 | Background activity launch restrictions | Foreground service workaround |
| Android 11 | Auto-revoke unused permissions | Malware periodically re-grants via accessibility |
| Android 11 | One-time permissions for camera/mic/location | Auto-grant repeats each session |
| Android 12 | Approximate vs precise location choice | Accessibility selects "Precise" option |
| Android 13 | Restricted settings for sideloaded apps | Session-based installer bypass |
| Android 13 | Notification permission now requires explicit grant | Auto-clicked via accessibility |
| Android 14 | Restricted settings expanded but session bypass persists | No change in dropper behavior |
| Android 15 | Expanded restricted settings enforcement | Session-based bypass partially patched |
Detection During Analysis¶
Static Indicators
BIND_ACCESSIBILITY_SERVICEin manifestfindAccessibilityNodeInfosByTextorfindAccessibilityNodeInfosByViewIdin decompiled code- References to
com.android.permissioncontrollerorcom.google.android.packageinstaller PackageInstaller.Sessionusage in dropper components- Intent actions targeting Settings screens (
ACTION_MANAGE_OVERLAY_PERMISSION, etc.)
Dynamic Indicators
- Rapid succession of permission grants after accessibility is enabled
- Settings app opened programmatically without user navigation
- Default SMS app changed immediately after accessibility grant
- Permission dialogs appearing and disappearing within milliseconds
Cross-References¶
- Accessibility Abuse -- the enabling technique for all permission manipulation
BIND_ACCESSIBILITY_SERVICE-- permission details and grant flow- Overlay Attacks -- often enabled by auto-granted
SYSTEM_ALERT_WINDOW - SMS Interception -- downstream abuse after SMS permissions are obtained
- Fake Biometric Prompts -- alternative PIN capture via overlay rather than biometric downgrade