-
海量代码中定位关键修改点 -
理解漏洞成因和影响范围 -
构建有效的验证程序
InstallPackageHelper: fiX the NPE problem.
Install the renamed apk,use the new name to getPackageLPr may be null,so we should make a null judgment.
Test: monkey test
Flag: EXEMPT bugfix
Bug: 386727719
Change-Id: Ia41a401bceaa13889ea66f5e3e337b99e3e4b799
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index f449126..d4efb5c 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1387,7 +1387,7 @@
boolean systemApp = false;
boolean replace = false;
synchronized (mPm.mLock) {
- final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
+ PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
// Check if installing already existing package
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mPm.mSettings.getRenamedPackageLPr(pkgName);
@@ -1398,14 +1398,15 @@
// name. We must continue using the original name, so
// rename the new package here.
parsedPackage.setPackageName(oldName);
- pkgName = parsedPackage.getPackageName();
- replace = true;
+ pkgName = oldName;
+ ps = mPm.mSettings.getPackageLPr(oldName);
if (DEBUG_INSTALL) {
Slog.d(TAG, "Replacing existing renamed package: oldName="
+ oldName + " pkgName=" + pkgName);
}
- } elseif (ps != null) {
- // This package, under its official name, already exists
+ }
+ if (ps != null) {
+ // This package, under its official name or its old name, already exists
// on the device; we should replace it.
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing package: " + pkgName);
-
当安装一个已经存在的包时,如果这个包之前被重命名过,原始代码会: -
设置新包的包名为旧名称 -
设置replace标志为true -
但没有重新获取PackageSetting对象 -
这可能导致后续逻辑中使用了错误的PackageSetting对象,可能允许攻击者绕过某些安全检查或导致不一致的状态。
-
在重命名包后,重新获取PackageSetting对象(ps = mPm.mSettings.getPackageLPr(oldName)) -
将replace标志的判断逻辑分开,确保在两种情况下都能正确设置replace标志
-
安装一个包A -
重命名包A为包B -
尝试再次安装包A,利用INSTALL_REPLACE_EXISTING标志 -
观察是否能够绕过某些安全检查或导致不一致的状态
- 准备恶意包
:创建一个与目标系统包同名的恶意APK - 利用重命名机制
: -
先安装一个合法包A(包名com.example.app) -
然后重命名该包(如改为com.example.app.old) -
此时系统会保留原始包名映射关系 - 触发漏洞逻辑
: -
安装恶意包时使用原始包名(com.example.app) -
由于修改后的代码会: -
先恢复原始包名(pkgName = oldName) -
重新获取PackageSetting(ps = mPm.mSettings.getPackageLPr(oldName)) -
然后通过独立if检查ps != null设置replace标志 -
这样可能绕过某些安全检查 - 实现提权
: -
如果成功替换系统关键包,可能获得系统权限 -
或者替换用户已安装应用,实现中间人攻击
-
原始包名:com.android.systemplugin -
被重命名为:com.android.systemplugin.old
-
恶意包被当作系统包安装 -
绕过签名验证(因为代码路径改变了验证顺序) -
获取系统级权限
-
用户执行的 pm <command> 会调用 Pm.run(),进而解析参数并调用 Pm.onCommand()。
- pm install 触发 PMS 安装流程
Pm.run() → Pm.runInstall() → 通过 Binder 调用 IPackageManager.installPackageAsUser()。 - PMS 处理安装请求
PackageManagerService.installPackageAsUser() → installPackageTracedLI() → installPackageLI()。 - 解析包名重命名规则
在扫描 APK 时(scanPackageTracedLI → scanPackageLI),PMS 会检查是否需要重命名: // PackageManagerService.java private PackageParser.Package scanPackageLI(...) throws PackageManagerException { // 检查是否存在需要重命名的包 if (mSettings.getRenamedPackages().containsKey(realPackageName)) { String newName = mSettings.getRenamedPackages().get(realPackageName); // 调用 addRenamedPackageLPw 更新设置 mSettings.addRenamedPackageLPw(realPackageName, newName); } } - 最终调用 addRenamedPackageLPw
该方法在 Settings.java 中实现,用于持久化包名映射关系: // frameworks/base/services/core/java/com/android/server/pm/Settings.java void addRenamedPackageLPw(String oldName, String newName) { mRenamedPackages.put(oldName, newName); writeLPr(); // 写入 packages.xml }
-
当此 APK 安装时,PMS 会自动调用 addRenamedPackageLPw 记录映射关系。
-
修改 /data/system/packages.xml,添加 <renamed-package> 标签: <renamed-package new="com.new.name" old="com.old.name" />运行 HTML -
通过 pm 强制 PMS 重新读取配置: adb shell pm clear com.android.providers.settings
- Settings.addRenamedPackageLPw()
添加 Slog.d(TAG, "Renamed package: " + oldName + " -> " + newName);。 - PackageManagerService.scanPackageLI()
检查 mSettings.getRenamedPackages() 的调用时机。
- 直接触发路径
: pm install → PMS.installPackageAsUser() → scanPackageLI() → Settings.addRenamedPackageLPw()。 - 必要条件
: 需要存在预定义的包名映射(通过 <original-package> 或 packages.xml)。 - 权限要求
: 此操作通常需要 系统权限(如 android.uid.system)或 root 访问。
原文始发于微信公众号(大山子雪人):用大模型探寻补丁代码的秘密 - 从漏洞挖掘到POC构建之旅
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论