通过Xposed获取待安装应用包名及拦截安装的技术问题
问题描述
我正在开发一款基于Xposed的模块,目标是实现应用安装黑名单功能,可拦截Google Play、ADB、系统安装器等所有渠道的指定应用安装。
目前计划通过hook android.content.pm.PackageInstaller 相关类实现,尝试hook PackageInstaller.SessionParams 的setAppPackageName方法获取待安装应用包名,但调用param.getResult()时返回null或随机值,拿不到有效包名,也找不到合适的其他hook方法,求助解决办法。
相关代码如下:
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { if (!lpparam.packageName.equals("com.google.android.packageinstaller")) return; hookPackageNameClass(lpparam); } private void hookPackageNameClass(XC_LoadPackage.LoadPackageParam lpparam) { Class<?> SessionParamsClass = XposedHelpers.findClass("android.content.pm.PackageInstaller.SessionParams", lpparam.classLoader); findAndHookMethod(SessionParamsClass, "setAppPackageName", String.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); XposedBridge.log("----1111 Obj hook----: " + param.thisObject); XposedBridge.log("----1111 Method hook----: " + param.method); XposedBridge.log("----1111 Args hook----: " + param.args); XposedBridge.log("----1111 result hook----: " + param.getResult().toString()); } }); }
解决方案
1. 修正当前hook方法的包名获取逻辑
setAppPackageName是**无返回值(void)**方法,所以param.getResult()必然返回null,你要的包名就在方法的入参里:
protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); // 从方法参数中提取待安装应用的包名 String packageName = (String) param.args[0]; XposedBridge.log("待安装应用包名: " + packageName); // 对比黑名单,命中则拦截 if (isInBlacklist(packageName)) { // 抛出异常终止安装流程 throw new SecurityException("该应用在黑名单中,禁止安装"); } }
2. 更可靠的hook点推荐
仅hooksetAppPackageName可能存在遗漏(比如部分安装流程直接构造SessionParams而不调用该方法),推荐以下覆盖更全面的hook点:
(1)hook PackageInstaller.Session的commit方法
这是安装流程的最终提交步骤,能确保拦截所有安装请求:
Class<?> sessionClass = XposedHelpers.findClass("android.content.pm.PackageInstaller.Session", lpparam.classLoader); findAndHookMethod(sessionClass, "commit", IntentSender.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); // 从Session对象中获取SessionParams实例 Object sessionParams = XposedHelpers.getObjectField(param.thisObject, "mParams"); // 从SessionParams中提取包名 String packageName = (String) XposedHelpers.getObjectField(sessionParams, "mAppPackageName"); if (isInBlacklist(packageName)) { XposedBridge.log("拦截黑名单应用安装: " + packageName); param.setThrowable(new SecurityException("禁止安装黑名单应用")); } } });
(2)hook PackageInstaller的install方法
拦截安装请求的入口,覆盖ADB、Google Play等多渠道:
Class<?> packageInstallerClass = XposedHelpers.findClass("android.content.pm.PackageInstaller", lpparam.classLoader); findAndHookMethod(packageInstallerClass, "install", String.class, String.class, IntentSender.class, int.class, String.class, Bundle.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); // 第一个参数是APK文件路径,可通过解析APK获取包名 String apkPath = (String) param.args[0]; String packageName = getPackageNameFromApk(apkPath); if (isInBlacklist(packageName)) { XposedBridge.log("拦截黑名单应用安装: " + packageName); param.setThrowable(new SecurityException("禁止安装黑名单应用")); } } });
3. 补充说明
- 解析APK包名可使用
PackageManager的getPackageArchiveInfo方法,注意要获取当前hook进程对应的PackageManager实例。 - 拦截优先使用
param.setThrowable()抛出异常,能彻底终止安装流程;修改参数或直接返回的方式可靠性较低。 - 不要仅限制hook
com.google.android.packageinstaller,需覆盖com.android.vending(Google Play)、系统进程等,可在handleLoadPackage中去掉包名判断,或添加多个目标包名的逻辑判断。
内容的提问来源于stack exchange,提问作者MHB
相关产品推荐
相关产品推荐

