赞
踩
Android有一个权限叫读取已安装应用列表,貌似不是原生权限,禁用后,应用就读不到系统的应用列表,只能读到它自己。
实测发现,这个权限形同虚设,利用该漏洞可以绕过读取应用列表权限获取所有应用,目前发现共有四种方法能读取到全部或部分应用列表,该bug截止目前未修补。
方法一:getPackageManager().queryIntent*
这种方法可以获取部分应用,在某些手机上无效。
方法二:adb shell命令
1.pm list packages 列表所有应用包名
2.dumpsys package 输出所有包信息
如果禁止了读取应用权限,在大部分手机上能获取全部应用,但在oppo手机上不起作用。
方法三:getPackageManager().GetPackagesForUid()
这种方法几乎是万能的,能获取全部应用列表。该方法称为暴力枚举法,遍历系统所有uid,并返回应用id(包名),拿到应用id,剩下只需要来个getPackageInfo即可,但是速度稍慢(慢了0点秒到1秒,其实已经算快了,正常获取应用列表慢的话也需要几秒),如果不要求完美,可以遍历其中一部分,比如前1000个,毕竟一般人的手机不可能装上千个应用。
以上三种方法,推荐方法三,具体实现时首先调用原始api(getInstalledPackages)获取应用列表,然后遍历列表判断是否包含包名为android(系统必需应用)的应用,或者判断其它也行,比如设置(com.android.settings),系统ui(com.android.systemui)等,如果不包含,则说明权限被禁,然后再强制读取应用。
第三种方法代码如下:
private static List<PackageInfo> forceGetPackageList(Context context) {
PackageManager pm = context.getPackageManager();
List<PackageInfo> mList = new ArrayList<>();
//系统应用uid从1000开始,用户应用uid从10000(FIRST_APPLICATION_UID)开始,直接合并查询
for (int i = Process.SYSTEM_UID; i <= Process.LAST_APPLICATION_UID; i++) {
String[] apps = null;
try {
apps = pm.getPackagesForUid(i);
} catch (Exception e) {
e.printStackTrace();
}
if (apps != null) {
for (String app : apps) {
try {
PackageInfo info = pm.getPackageInfo(app, 0);
if (info != null) {
mList.add(info);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return mList;
}
方法四:遍历/data/app/目录下的apk文件,调用getPackageArchiveInfo获取包名可得到第三方应用列表,遍历/system/app,/system/preload,/system/preinstall等目录可得到系统应用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。