菜单

安卓应用程序

相关源文件

目的与范围

本文档详细介绍了 Magisk Android 应用程序的架构和实现,该应用程序是与 Magisk 系统交互的主要用户界面。该应用程序负责 Magisk 的安装、配置、模块管理和更新。本文档侧重于应用程序本身的技术方面,特别是其存根 APK 系统、动态代码加载和反检测机制。

有关设备上 Magisk 安装过程的信息,请参阅 安装系统。有关模块系统详情,请参阅 模块系统

概述架构

Magisk Android 应用程序采用复杂的架构,旨在方便更新和避免被检测,同时为用户提供完整的功能。

来源:app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java1-120

Stub APK 系统

存根 APK 系统是 Magisk 应用程序架构的关键组成部分。它包含一个安装在设备上的最小化 APK,该 APK 在运行时动态加载完整的 Magisk 应用程序。

存储结构

存根 APK 系统在应用程序的数据目录中维护两个重要文件:

  • current.apk:动态加载的当前活动的完整 Magisk 应用程序
  • update.apk:在应用更新之前暂存待更新版本

来源:app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java23-56

动态加载机制

存根 APK 通过两种机制加载完整应用程序:

  1. 代码加载:使用 DynamicClassLoader 从完整 APK 加载 Java 类
  2. 资源加载:使用 ResourcesLoader (Android 11+) 或反射(较旧的 Android)加载资源

来源:app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java57-85 app/shared/src/main/java/com/topjohnwu/magisk/utils/DynamicClassLoader.java1-65

动态类加载

DynamicClassLoader 扩展了 Android 的 BaseDexClassLoader,为动态加载的 APK 提供自定义类加载机制。

类加载顺序

DynamicClassLoader 在加载类时遵循特定顺序:

  1. 检查类是否已加载
  2. 尝试从系统类加载器(启动类路径)加载
  3. 尝试在当前 DEX(完整的 Magisk APK)中查找类
  4. 最后,尝试父类加载器

此顺序可确保正确的类解析,同时优先考虑来自动态加载的 APK 的类。

来源:app/shared/src/main/java/com/topjohnwu/magisk/utils/DynamicClassLoader.java23-46

APK 安装和更新

Magisk 应用包含一个用于自我更新和以编程方式安装其他 APK 的机制。

安装会话

APKInstall 工具使用 Android 的 PackageInstaller API 创建安装会话。

此系统允许 Magisk 应用:

  1. 安装自身的更新
  2. 根据功能需要安装其他 APK
  3. 处理安装所需的用户操作

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

组件混淆

为了避免被检测,Magisk 应用采用了复杂的混淆技术来处理其 Android 组件。

组件名称随机化

Magisk 构建系统会为 Android 组件生成随机名称,以避免通过组件名称匹配进行检测。

构建系统

  1. 生成随机包名和类名
  2. 使用这些随机名称更新 Android manifest
  3. 创建真实组件类与随机化名称之间的映射

来源:buildSrc/src/main/java/Codegen.kt73-181

Manifest 生成过程

在构建过程中,Magisk 会生成一个带有随机组件名称的 manifest。

Manifest 包含随机打乱的组件:

  • 用于文件访问的内容提供程序 (Content Provider)
  • 用于系统事件的广播接收器 (Broadcast Receiver)
  • 主 Activity 和辅助 Activity
  • 用于后台操作的服务 (Service)

来源:buildSrc/src/main/java/Codegen.kt98-181

资源加密

为了进一步保护应用程序免受分析,Magisk 构建系统会加密资源。

在运行时,存根应用程序会:

  1. 使用嵌入式密钥解密资源
  2. 加载解密后的资源供完整应用程序使用

来源:buildSrc/src/main/java/Codegen.kt231-261

数据结构

存根 APK 系统维护着某些数据结构,以促进存根与完整应用程序之间的通信。

索引区目的类型描述
0STUB_VERSION整数存根 APK 的版本
1CLASS_COMPONENT_MAPMap<String, String>将类名映射到组件名称
2ROOT_SERVICEClass<?>根服务类

此数据结构允许存根应用程序正确路由意图并从完整应用程序加载正确的组件。

来源:app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java95-119

应用重启机制

在必要时(例如更新后),应用程序可以自行干净地重启。

此过程可确保在更新或配置更改后应用程序能够干净地重启。

来源:app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java87-93

与 Magisk 系统的集成

Android 应用程序作为主要用户界面与更广泛的 Magisk 系统集成。

Android 应用程序提供:

  1. 用于控制 Magisk 功能的用户界面
  2. 模块安装和管理
  3. 设置配置
  4. 自我更新功能

通过这些接口,Android 应用程序允许用户与运行在设备较低级别的核心 Magisk 系统进行交互。