菜单

应用隐藏机制

相关源文件

目的与范围

本文档详细介绍了 Magisk 的应用隐藏机制,该机制允许 Magisk 应用在安装过程中通过更改其身份和包名来隐藏自身,以避免被检测。此功能对于需要通过 SafetyNet 验证或隐藏 root 权限免遭主动检查 Magisk 存在的应用程序的用户至关重要。

本页面专门关注 Magisk 应用本身的隐藏技术实现。有关隐藏 root 权限免遭其他应用程序检测的信息,请参阅拒绝列表系统文档。

概述

应用隐藏机制依赖于 Android 的 PackageInstaller API,以随机化的包名重新安装 Magisk 应用。此过程有效地创建了一个具有不同身份的 Magisk 应用“克隆”,使其难以被搜索 Magisk 标准包名的应用程序检测到。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java

技术实现

APKInstall 工具

应用隐藏机制的核心实现在 APKInstall 工具类中。该类提供了使用 Android 的 PackageInstaller API 以编程方式安装 APK 文件的便捷接口。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java28-174

关键组件

  1. APKInstall 类:提供用于促进 APK 安装的静态方法

    • transfer():在流之间复制数据的实用方法
    • registerReceiver():用于注册广播接收器的平台兼容方法
    • startSession():创建并初始化安装会话
  2. Session 接口:定义了安装会话的契约

    • openStream():打开一个输出流以写入 APK 数据
    • waitIntent():等待并返回安装所需的任何用户操作 Intent
  3. InstallReceiver 类:实现 Session 接口并继承 BroadcastReceiver

    • 处理安装事件和回调
    • 管理安装会话的生命周期
    • 处理安装成功、失败和用户操作要求

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java28-67 app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java74-174

安装流程

隐藏 Magisk 应用的安装遵循特定序列,利用 Android 的 PackageInstaller API

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java49-65 app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java90-126 app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java148-173

详细的技术工作流程

1. 会话初始化

该过程始于对 APKInstall.startSession() 的调用,该调用

  1. 创建一个新的 InstallReceiver,并提供一个可选的包名进行监视
  2. 注册安装事件和包添加事件(如果提供了包名)
  3. 返回一个 Session 接口供调用者使用

如果提供了包名,系统还将监视 ACTION_PACKAGE_ADDED 事件,以检测指定的包是否成功安装。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java49-65

2. APK 传输

用于写入 APK 数据

  1. 调用者通过 session.openStream(context) 请求输出流
  2. InstallReceiver 创建具有适当参数的 PackageInstaller 会话
  3. 打开一个写入流到会话
  4. 通过此流传输 APK 数据
  5. 关闭流时,会话会自动提交

用于安装的 SessionParams 包含 MODE_FULL_INSTALL,并且在 Android S 及更高版本上,用户操作要求被明确禁用以简化安装过程。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java148-173

3. 安装事件处理

InstallReceiver 处理安装事件

  1. STATUS_PENDING_USER_ACTION:捕获需要呈现给用户的 Intent
  2. STATUS_SUCCESS:如果未指定包名,则触发 onSuccess 回调
  3. 其他状态:被视为失败,触发会话中止和 onFailure 回调

如果指定了包名,接收器还将监视与该包匹配的 ACTION_PACKAGE_ADDED 广播,这表示安装成功。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java90-126

4. 用户交互处理

如果需要用户交互(在较旧的 Android 版本中很常见)

  1. waitIntent() 方法返回必须呈现给用户的 Intent
  2. 此 Intent 通常会启动 Android 包安装确认对话框
  3. 调用者负责启动此 Intent 并处理结果

使用 CountDownLatch 确保 waitIntent() 方法在收到安装状态或 5 秒超时之前一直阻塞。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java139-145

安全考量

应用隐藏机制通过多种方式增强了安全性

  1. 随机身份:每次安装都会创建唯一的包名,使检测算法难以识别 Magisk 应用
  2. 干净的安装:使用 PackageInstaller API 可确保使用所有 Android 安全检查进行正确安装
  3. 无缝更新:该机制处理不同应用身份之间的过渡,以保持功能

由于 APK 数据可以在安装前进行修改,因此该系统不仅允许更改包名,还可能进行其他进一步混淆应用身份的修改。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java

兼容性考虑因素

该实现包含了针对不同 Android 版本的兼容性措施

  1. 在 Android 8.0+(Oreo)上,它使用 Context.RECEIVER_NOT_EXPORTED 标志来注册接收器
  2. 在 Android S+(12+)上,它在会话参数中显式设置了 USER_ACTION_NOT_REQUIRED
  3. 对于 Intent 处理,它使用 FLAG_MUTABLEFLAG_UPDATE_CURRENT 来创建 PendingIntent

这些调整确保了该机制在各种 Android 版本上都能可靠运行。

来源: app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java39-47 app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java155-158 app/shared/src/main/java/com/topjohnwu/magisk/utils/APKInstall.java149-152

总结

应用隐藏机制使 Magisk 能够通过以不同的包身份安装来隐藏其存在。此功能对于需要避免 SafetyNet 或其他 root 检测系统检测的用户至关重要,同时仍可保持 Magisk 的全部功能。

该实现利用 Android 的 PackageInstaller API 和广播系统,以一种干净、安全且适用于不同 Android 版本的方式处理安装过程。