Guardsquare recommended technique
This technique is an extension of accessibility services allow-listing.
Yet another criterion for considering applications as suspicious is whether they have enabled accessibility services and they are side-loaded. The implementation is shown in the snippet below:
private List<String> getListOfSideLoadedAppsWithEnabledAccessibilityServices(
Context context) {
Set<String> installerAllowList = Set.of(
"com.android.vending",
"com.sec.android.app.samsungapps",
// ...
"com.huawei.appmarket");
List<AccessibilityServiceInfo> a11yServiceList =
getListOfEnabledA11yServices(context);
List<String> sideLoadedA11yAppList = new ArrayList<>();
PackageManager packageManager = context.getPackageManager();
String packageName;
String installer;
for (AccessibilityServiceInfo asi : a11yServiceList) {
packageName = asi.getId().split("/")[0];
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
installer = packageManager.
getInstallSourceInfo(packageName).
getInstallingPackageName();
} else {
installer = packageManager.getInstallerPackageName(packageName);
}
if (installer == null || !installerAllowList.contains(installer)) {
Log.d("APP_INSPECTOR", "[!] app '" + packageName +
"' has a11y enabled and is side-loaded");
sideLoadedA11yAppList.add(packageName);
}
} catch(PackageManager.NameNotFoundException e) {
// (...)
}
}
return sideLoadedA11yAppList;
}
private fun getListOfSideLoadedAppsWithEnabledAccessibilityServices(
context: Context
): List<String> {
val installerAllowList = setOf(
"com.android.vending",
"com.sec.android.app.samsungapps",
// ...
"com.huawei.appmarket"
)
val a11yServiceList = getListOfEnabledA11yServices(context)
val sideLoadedA11yAppList: MutableList<String> = ArrayList()
val packageManager = context.packageManager
var packageName: String
var installer: String?
for (asi in a11yServiceList) {
packageName =
asi.id.split("/".toRegex()).dropLastWhile {
it.isEmpty() }.toTypedArray()[0]
try {
installer = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
packageManager.getInstallSourceInfo(packageName)
.installingPackageName
} else {
packageManager.getInstallerPackageName(packageName)
}
if (installer == null || !installerAllowList.contains(installer)) {
Log.d(
"APP_INSPECTOR", "[!] app '" + packageName +
"' has a11y enabled and is side-loaded"
)
sideLoadedA11yAppList.add(packageName)
}
} catch (e: PackageManager.NameNotFoundException) {
// (...)
}
}
return sideLoadedA11yAppList
}
Other mobile app stores to consider in your detection code:
- Google
- Samsung
- Amazon
- Huawei
- Xiaomi
- OPPO
- Vivo