Guardsquare recommended technique
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
}