Tracking device admin accessibility services

      Technique summary
    Technique Tracking decide admin accessibility services
    Against Malicious accessibility services
    Limitations None
    Side effects None
    Recommendations Recommended for use combined with other techniques for older devices

    This technique is an extension of accessibility services allow-listing.

    A common malware workflow pattern is to obtain accessibility service rights, and later also device admin rights. Therefore, a strategy could be to check applications that have both privileges.

    This code can be used to enumerate accessibility services:

    private List<AccessibilityServiceInfo> getListOfEnabledA11yServices(Context context) { AccessibilityManager am =(AccessibilityManager) context. getSystemService(Context.ACCESSIBILITY_SERVICE); return am.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK); } private fun getListOfEnabledA11yServices(context: Context): List<AccessibilityServiceInfo> { val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager return am.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK) }

    The next block of code would enumarate device admin apps:

    private List<String> getListOfDeviceAdminApps(Context context) { List<String> deviceAdminAppList = new ArrayList<>(); DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context. getSystemService(Context.DEVICE_POLICY_SERVICE); List<ComponentName> activeDeviceAdminComp = devicePolicyManager.getActiveAdmins(); if (activeDeviceAdminComp != null) { for (ComponentName cn : activeDeviceAdminComp) { deviceAdminAppList.add(cn.getPackageName()); } } return deviceAdminAppList; } private fun getListOfDeviceAdminApps(context: Context): List<String> { val deviceAdminAppList: MutableList<String> = ArrayList() val devicePolicyManager = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager val activeDeviceAdminComp = devicePolicyManager.activeAdmins if (activeDeviceAdminComp != null) { for (cn in activeDeviceAdminComp) { deviceAdminAppList.add(cn.packageName) } } return deviceAdminAppList }

    And finally, this block of code will check whether there is any app in both lists:

    public List<String> getListOfDeviceAdminAppsWithEnabledAccessibilityServices( Context context) { List<String> suspiciousAppList = new ArrayList<>(); List<AccessibilityServiceInfo> a11yServiceList = getListOfEnabledA11yServices(context); List<String> deviceAdminAppList = getListOfDeviceAdminApps(context); for (AccessibilityServiceInfo asi : a11yServiceList) { String id = asi.getId(); for (String packageName: deviceAdminAppList) { if (id.contains(packageName)) { Log.d("APP_INSPECTOR", "[!] app '" + packageName + "' is suspicious (a11y + device admin)"); suspiciousAppList.add(packageName); } } } return suspiciousAppList; } fun getListOfDeviceAdminAppsWithEnabledAccessibilityServices( context: Context ): List<String> { val suspiciousAppList: MutableList<String> = ArrayList() val a11yServiceList = getListOfEnabledA11yServices(context) val deviceAdminAppList = getListOfDeviceAdminApps(context) for (asi in a11yServiceList) { val id = asi.id for (packageName in deviceAdminAppList) { if (id.contains(packageName)) { Log.d( "APP_INSPECTOR", "[!] app '" + packageName + "' is suspicious (a11y + device admin)" ) suspiciousAppList.add(packageName) } } } return suspiciousAppList }

     

    Guardsquare

    Table of contents