leolovenet/Zygisk-FridaGadget

GitHub: leolovenet/Zygisk-FridaGadget

一个基于 Zygisk 的 Magisk 模块,用于在 frida-server 无法稳定运行的设备上,通过配置将 Frida Gadget 选择性注入目标 Android 进程。

Stars: 0 | Forks: 0

# Zygisk - Frida Gadget 这是一个通过配置驱动的 Zygisk 模块,用于将 Frida Gadget 注入到选定的 Android 应用进程中。 默认的示例目标是 `com.example.app`,但目标是在 `targets.conf` 中配置的,不需要修改 C++ 代码。 ## 使用场景 当 `frida-server` 无法在设备上稳定运行时(例如由于厂商限制、进程隐藏、可执行文件映射策略或其他运行时限制),本模块旨在作为基于 Frida Gadget 的替代方案。 该模块不会启动全局的 `frida-server`,而是利用 Zygisk 进入选定的应用进程,并仅为已配置的目标加载 Frida Gadget。 ## 负责任地使用 本项目适用于对您拥有或已获得明确授权的设备与应用程序,进行合法的安全研究、调试、兼容性分析以及防御性测试。 未经授权,请勿使用本项目访问、修改、埋点或监控任何应用程序、系统或数据。 ## 运行环境要求 - Magisk 27001 / Kitsune Magisk(需启用 Zygisk) ## 构建要求 - Android NDK r26+ - `ndk-build` - Python 3 ## 在 macOS 上配置 NDK ``` export ANDROID_NDK_HOME=/path/to/android-ndk-r26d export PATH="$ANDROID_NDK_HOME:$PATH" ``` ## 下载 Frida Gadget 从 Frida 官方发布页面下载 Android Gadget: ``` https://github.com/frida/frida/releases ``` 请使用与您的目标设备/应用相匹配的 ABI 文件: ``` frida-gadget--android-arm64.so.xz frida-gadget--android-arm.so.xz ``` 解压后,如果您愿意,可以保留源文件名中的版本号: ``` gadget/ arm64-v8a/ .gitkeep libgadget-17.15.3.so libgadget.so -> libgadget-17.15.3.so armeabi-v7a/ .gitkeep libgadget-17.15.3.so libgadget.so -> libgadget-17.15.3.so libgadget.config.so ``` 这是发布版本的推荐目录结构,因为多个 Gadget 版本可以共存,同时由 `libgadget.so` 来选择要部署的版本。在部署期间,模块会解析所选的真实文件,并将其作为以下名称复制到目标应用的 native lib 目录中: ``` libgadget.so ``` 保持部署后的文件名稳定是刻意为之的:Frida Gadget 会在已加载的 `libgadget.so` 旁边自动发现 `libgadget.config.so`。 `.gitkeep` 文件仅在克隆仓库时用于保持 ABI 目录的存在。它们在运行时不会被使用。 源文件名也可以是纯净的格式: ``` gadget/arm64-v8a/libgadget.so gadget/armeabi-v7a/libgadget.so ``` 每个 ABI 目录的选择规则: ``` 1. If libgadget.so is a symlink, its target is used. 2. If libgadget.so is a small selector file, its contents are treated as the selected Gadget path. 3. If libgadget.so is a regular Gadget file, that file is used. 4. If libgadget.so is missing and exactly one versioned Gadget file exists, deployment creates libgadget.so as a symlink to it. 5. If multiple versioned Gadget files exist and libgadget.so is missing, deployment is skipped for that ABI and deploy.log records the ambiguity. ``` 选择器文件适用于简短的相对路径名称(例如 `libgadget-17.15.3.so`),或者在您确实需要时使用绝对路径。大于 256 字节的文件将被视为真实的 `.so` 文件,而不是选择器。这使得选择器路径配置更加灵活,同时避免了意外将二进制文件误判为选择器。 要切换版本,请更新软链接并再次运行 `action.sh`: ``` adb shell su -c 'cd /data/adb/modules/zygisk_frida_gadget/gadget/arm64-v8a && ln -sf libgadget-17.15.3.so libgadget.so' adb shell su -c '/data/adb/modules/zygisk_frida_gadget/action.sh' ``` ## Gadget 配置 将 Gadget 配置文件放在项目根目录: ``` libgadget.config.so ``` 您也可以将特定 ABI 的配置文件放在 Gadget 二进制文件旁边: ``` gadget/arm64-v8a/libgadget.config.so gadget/armeabi-v7a/libgadget.config.so ``` 特定 ABI 的配置优先于根目录的配置。 ## 配置目标 编辑 `targets.conf`: ``` # package|process|match|abi com.example.app|com.example.app|exact|auto ``` 字段说明: ``` package: target Android package name, used for deployment under /data/app process: optional target process name, compared with args->nice_name from Zygisk match: optional process-name matching mode, defaults to exact abi: optional Gadget ABI selection, defaults to auto ``` 如果省略 `process` 或将其留空,则默认使用包名。以下形式是等价的: ``` com.example.app com.example.app| com.example.app|com.example.app com.example.app|com.example.app|exact com.example.app|com.example.app|exact|auto ``` 支持的 `match` 值: ``` exact prefix suffix contains ``` `match` 控制如何将配置的 `process` 值与真实的进程名称进行比较: ``` exact: load only when process name is exactly equal prefix: load when process name starts with the configured value suffix: load when process name ends with the configured value contains: load when process name contains the configured value ``` 对于大多数应用,建议从 `exact` 开始,以避免无意中注入子进程、沙箱或服务进程。仅当您有意要覆盖多个相关进程时,才使用 `prefix`、`suffix` 或 `contains`。 支持的 `abi` 值: ``` auto arm64-v8a armeabi-v7a ``` 当配置为 `abi=auto` 时,如果 `lib/arm64` 目录存在,部署程序会将 arm64 Gadget 复制到该目录;如果 `lib/arm` 目录存在,则将 arm Gadget 复制到该目录。 在运行时,native loader 也会根据当前进程的位数选择已部署的 payload 路径。64 位进程会在 `lib/arm64` 下查找,而 32 位进程会在 `lib/arm` 下查找;仅当特定 ABI 目录中没有提供 `libgadget.so` 时,两者才会回退到 `lib` 目录。 `abi` 字段是可选的。如果省略,默认值为 `auto`: ``` com.example.app|com.example.app|exact ``` ## 调试日志 编辑 `module.conf`: ``` debug=0 ``` 设置 `debug=1` 以记录非目标进程的检查信息以及其他详细的匹配细节。 重要日志将始终输出: - 匹配到目标 - 已解析 payload 路径 - 开始加载 payload - dlopen 成功/失败 ## 构建 ``` ./build.sh ``` 输出: ``` out/zygisk_frida_gadget.zip ``` `build.sh` 是一个围绕 `build.py` 的小型兼容性包装脚本。使用 Python 是为了实现确定性的 zip 打包,并在不依赖特定平台 `zip` 命令的情况下保留 Unix 文件模式/软链接。 默认情况下,如果缺少 Gadget 二进制文件或配置文件,只会产生警告,因此您可以先构建 loader,稍后再添加 Gadget。对于发布构建,请使用严格模式: ``` STRICT_BUILD=1 ./build.sh ``` ## 更新 当 `module.prop` 包含以下内容时,兼容 Magisk 的模块管理器可以检查更新: ``` updateJson=https://raw.githubusercontent.com/leolovenet/Zygisk-FridaGadget/main/update.json ``` 更新元数据发布在 `update.json` 中,并指向附加到相应 GitHub 发布标签的发布 zip 包。发布新版本时,请同时更新以下值: ``` module.prop: version, versionCode update.json: version, versionCode, zipUrl CHANGELOG.md: release notes ``` 然后构建 `out/zygisk_frida_gadget.zip`,并将其上传到标签与 `zipUrl` 相匹配的 GitHub Release 中。 ## 安装 在 Magisk 中安装: ``` Magisk -> Modules -> Install from storage ``` 安装后请重启设备。 ## 无需重启重新部署 native loader 会在每个应用进程启动时读取 `targets.conf`。如果您仅更改了进程匹配规则,并且该包已经部署过 Gadget,请强制停止并重启目标应用。 如果您添加了新包、更改了 Gadget 文件,或者需要重新部署到目标应用的 native lib 目录中,请运行: ``` adb shell su -c '/data/adb/modules/zygisk_frida_gadget/action.sh' ``` 某些 Magisk 管理器会为提供 `action.sh` 的模块显示一个“操作”按钮。如果该按钮可用,点击它将运行相同的重新部署流程并打印 `deploy.log`。如果您的 Magisk/Kitsune 版本只显示“卸载”,请使用上述的 adb 命令。 然后强制停止并重启目标应用: ``` adb shell am force-stop com.example.app ``` ## 工作原理 1. `customize.sh` 在模块安装期间运行。 2. `service.sh` 在开机后运行并重试部署。 3. `deploy_gadget.sh` 读取 `targets.conf`。 4. 对于每个目标,它使用 `pm path` 定位应用安装目录。 5. 它将 Frida Gadget 和配置文件复制到目标应用的 native library 目录中,例如: ``` /data/app//lib/arm64/libgadget.so /data/app//lib/arm64/libgadget.config.so ``` 6. 它会同步该目录中已有 `.so` 文件的 owner(所有者)、group(用户组)、mode(权限模式)和 SELinux context(上下文)。 7. Zygisk 模块读取 `targets.conf`,匹配当前进程名称,从 `/proc/self/maps` 或 `/data/app` 解析当前应用安装目录,检查 Gadget 是否已映射到进程中,并调用: ``` dlopen(payload_path, RTLD_NOW | RTLD_GLOBAL); ``` 因为 Gadget 是从应用 native library 目录加载的,所以 Frida 可以从同一目录读取 `libgadget.config.so`,而无需向应用进程开放 `/data/adb` 的访问权限。 如果进程已经映射了配置的 payload 路径、`libgadget.so` 或带有版本号的 `libgadget-*.so`,loader 会记录 `payload already loaded, skip dlopen`,并且不会再次加载 Gadget。 ## 限制 - 当前的部署路径是 `/data/app` 下的目标应用 native library 目录。 - 应用更新可能会替换安装目录,因此在更新目标应用后,请再次运行 `action.sh`。 - 当前的脚本仅处理 `arm64-v8a` 和 `armeabi-v7a` 架构的 Gadget 包。 - 该模块不尝试隐藏 Frida 的痕迹;它仅提供一种实用的 Gadget 加载途径。 ## 日志 ``` adb logcat -s ZygiskFridaGadget adb logcat | grep -i Frida ``` 部署日志写入到: ``` /data/adb/modules/zygisk_frida_gadget/deploy.log ``` ## 验证部署 ``` adb shell su -c 'find /data/app -name "libgadget*.so" -ls' adb shell su -c 'ls -lZ /data/app/*/lib/arm64/libgadget* 2>/dev/null' ``` ## 清理 移除 Magisk 模块时会运行 `uninstall.sh`,该脚本会从已配置的目标应用 native lib 目录中删除已部署的 `libgadget.so` 和 `libgadget.config.so`。 ## 安全提示 该模块刻意避免扩大 `/data/adb` 的权限;相反,Gadget 和配置文件会被部署到目标应用的 native lib 目录中。
标签:Android, Docker支持, DSL, Frida, Zygisk, 云资产清单, 目录枚举, 移动安全, 逆向工具, 逆向工程