SECFORCE/droidground

GitHub: SECFORCE/droidground

专为 Android CTF 竞赛设计的挑战平台,通过受控的运行时环境让选手在真实设备上完成漏洞利用挑战,避免 flag 被静态分析轻易提取。

Stars: 114 | Forks: 7


droidground

DroidGround


Website | Demo

在传统的 **CTF 挑战** 中,通常会将 flag 隐藏在系统的文件中,要求攻击者利用漏洞来获取它们。然而,在 Android 领域,这种方式并不奏效。APK 文件很容易被下载和逆向,因此 **将 flag 放置在设备上通常使其极易** 通过静态分析或模拟器技巧被提取出来。这严重限制了创建逼真的、基于运行时的挑战的能力。 _DroidGround_ 正是为了解决这个问题而设计的。 它是一个为在 **受控** 且 **逼真** 的环境中举办 Android 移动黑客挑战而定制的平台,在这里 **攻击者受到足够的限制**,从而必须以预期的方式来解决挑战。 重要的是,参与者可能会被 **限制在应用环境中**。该工具的模块化设计允许设置用户是否可以生成 shell、读取任意文件或侧载工具。一切都可以进行设置,使得获取 flag 的唯一途径就是理解并利用应用本身。 ## 📋 目录 - [🧭 概述](#-overview) - [✨ 功能特性](#-features) - [📸 截图](#-screenshots) - [⚙️ 配置](#️-configuration) - [🧩 用例](#-use-cases) - [⚙️ 使用方法](#️-usage) - [💡 提示](#-tips) - [🛠 开发](#-development) - [🤝 贡献](#-contributing) - [📚 致谢](#-credits) - [🪪 许可证](#-license) ## 🧭 概述 _DroidGround_ 能够实现各种传统 CTF 设置中难以实施的 _Android_ 挑战。例如,在远程代码执行 (RCE) 挑战中,选手可能会收到一个 APK 用于本地分析。在发现漏洞后,他们可以开发一个 Frida 脚本,并通过 DroidGround 在真实的目标设备上运行,以从内部存储中提取 flag。其他类型的挑战可以包括隐藏的 Activity、自定义广播 Intent、Service 漏洞利用,或使用预加载工具进行动态分析。 凭借实时设备流传输、精细的功能控制、Frida 集成以及可自定义的设置和重置脚本,DroidGround 使 CTF 组织者能够构建安全、灵活且逼真的 Android 挑战,远远超越了传统的可能范畴。 ## ✨ 功能特性 DroidGround 提供了一组丰富的由服务器控制的功能。 - **实时设备屏幕** (通过 `scrcpy`) - **重置挑战状态** - **重启应用 / 启动 Activity / 启动 Service** - **发送广播 Intent** - **关闭 / 重启设备** - **下载 Bugreport (bugreportz)** - **Frida 脚本编写** - 从预加载库运行 (受限模式) - 运行任意脚本 (完全模式) - **文件浏览器** - **终端访问** - **APK 管理** - **Logcat 查看器** - **Exploit 服务器** (如果启用了团队模式) 几乎所有功能都是 **模块化** 的,并通过环境变量进行定义,确保对挑战范围进行精确控制。 ## 📸 截图 | ![Screenshot Overview](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/33ffd3cb2d062942.png) | ![Screenshot Start Activity](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/896ce94287062943.png) | | ------------------------------------------------------ | ----------------------------------------------------- | | 概述 | 启动 Activity | | ![Screenshot Frida Jailed Mode](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/7902f23aa2062945.png) | ![Screenshot Frida Full Mode](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/a751baa6f6062946.png) | | Frida 受限模式 | Frida 完全模式 | | ![Screenshot File Browser](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/7dbbae536a062947.png) | ![Screenshot App Manager](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/7fd77a9914062948.png) | | 文件浏览器 | 应用管理器 | | ![Screenshot Terminal](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/8b0f181494062950.png) | ![Screenshot Logs](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/4a136f1463062951.png) | | 终端 | 日志 | ## ⚙️ 配置 根目录中的 `.env.sample` 文件是一个很好的起点。以下是当前支持的所有环境变量的完整列表: | 变量 | 描述 | 默认值 | | ------------------------------------- | --------------------------------------------------------------------------------- | ----------- | | `DROIDGROUND_BASE_PATH` | Web 应用的路径(适用于在子路径上托管) | - | | `DROIDGROUND_APP_PACKAGE_NAME` | 目标应用的包名 | - | | `DROIDGROUND_ADB_HOST` | ADB 主机 | `localhost` | | `DROIDGROUND_ADB_PORT` | ADB 端口 | `5037` | | `DROIDGROUND_ADB_SERIAL` | 可选的要连接的 ADB 设备序列号 | - | | `DROIDGROUND_DEVICE_TYPE` | `usb` 或 `network` | `usb` | | `DROIDGROUND_DEVICE_HOST` | Android 设备的 IP (`adb`) (仅限网络模式) | - | | `DROIDGROUND_DEVICE_PORT` | Android 设备的端口 (`adb`) (仅限网络模式) | - | | `DROIDGROUND_INIT_SCRIPTS_FOLDER` | 包含 `setup.sh` 和 `reset.sh` 的文件夹 | `/init.d` | | `DROIDGROUND_HOST` | 绑定地址 | `0.0.0.0` | | `DROIDGROUND_PORT` | 绑定端口 | `4242` | | `DROIDGROUND_RESTART_APP_DISABLED` | 禁用应用重启 | `false` | | `DROIDGROUND_APP_MANAGER_DISABLED` | 禁用应用管理器 | `false` | | `DROIDGROUND_BUG_REPORT_DISABLED` | 禁用 bugreport | `false` | | `DROIDGROUND_FILE_BROWSER_DISABLED` | 禁用文件浏览器 | `false` | | `DROIDGROUND_FRIDA_DISABLED` | 禁用 Frida 支持 | `false` | | `DROIDGROUND_FRIDA_TYPE` | `jail` 或 `full` | `jail` | | `DROIDGROUND_FRIDA_INJECTION` | `server` 或 `gadget` | `server` | | `DROIDGROUND_LOGCAT_DISABLED` | 禁用 logcat | `false` | | `DROIDGROUND_REBOOT_ENABLED` | 启用重启 | `false` | | `DROIDGROUND_SHUTDOWN_ENABLED` | 启用关闭 | `false` | | `DROIDGROUND_START_ACTIVITY_DISABLED` | 禁用 startActivity | `false` | | `DROIDGROUND_START_RECEIVER_DISABLED` | 禁用广播 | `false` | | `DROIDGROUND_START_SERVICE_DISABLED` | 禁用 startService | `false` | | `DROIDGROUND_TERMINAL_DISABLED` | 禁用终端 | `false` | | `DROIDGROUND_RESET_DISABLED` | 禁用重置 | `false` | | `DROIDGROUND_EXPLOIT_APP_DURATION` | exploit 应用保持活动状态的时间(以秒为单位) | `10` | | `DROIDGROUND_EXPLOIT_APP_MAX_SIZE` | exploit 应用的最大大小(以 MB 为单位) | `50` | | `DROIDGROUND_NUM_TEAMS` | 同时进行比赛的队伍数量 | - | | `DROIDGROUND_TEAM_TOKEN_` | 第 n 个队伍的 token。如果缺失则自动生成 | - | | `DROIDGROUND_IP_STATIC` | 要显示的静态 IP 地址。它的优先级高于 `DROIDGROUND_IP_IFACE` | - | | `DROIDGROUND_IP_IFACE` | 显示 IP 地址对应的网络接口 | - | | `DROIDGROUND_LOGO_LINK` | 可选设置 logo 点击跳转链接(例如,你的 CTF 主页) | - | `DROIDGROUND_IP_IFACE` 会首先寻找完全匹配项,如果找不到,则回退到第一个以提供的值 _开头_ 的接口,因为 Docker 只允许在容器内指定网络接口 **前缀**。 使用 `DROIDGROUND_NUM_TEAMS` 变量会在底层稍微改变应用程序的行为。如果设置了此选项: 1. exploit 服务器功能被启用,允许每个队伍通过其 **_team token_** 使用自己独立的(非常简单的)exploit 服务器。 2. 安装和运行 exploit 应用将 **要求** 提供 team token。每个安装的应用都会绑定到一个队伍,其他队伍将无法运行它。 这允许在可以通过网络请求窃取 flag 的挑战中,与多个队伍共享同一个 DroidGround 实例。这 **极大地降低了 CTF 比赛中 DroidGround 的部署成本**。 此外,如果该值设置为 `-1`,它将启用所谓的 **无限队伍** 模式。在此模式下,_Overview_ 页面中将提供一个用于生成新 **_team token_** 的按钮。如果启用此模式,所有的 `DROIDGROUND_TEAM_TOKEN_` 变量都将被忽略。 ## 🧩 用例 以下是 DroidGround 的一些使用方式: 1. **隐藏的 Activity**:找到并启动一个未暴露的 Activity 以查看 flag(选手的应用包含一个虚假 flag)。 2. **RCE**:应用存在 RCE 漏洞,且 flag 存储在设备上。 3. **Frida Instrumentation**:重载某个方法,并使用脚本从私有内存中提取 flag。 ## ⚙️ 使用方法 [examples](./examples/apps) 文件夹中提供了几个 _Docker Compose_ 示例文件。它们使用了 [DroidGround 示例仓库](https://github.com/SECFORCE/droidground-samples) 中的应用,这些应用将逐步完善以展示所有关键功能。它们也是了解如何设置你自己的 CTF 的良好起点。 在启动时,_DroidGround_ 会执行以下操作: 1. 建立与 `adb` 的连接 2. 如果存在,则运行由 `DROIDGROUND_INIT_SCRIPTS_FOLDER` 指定文件夹中的 `setup.sh`。此脚本可用于安装目标应用以及初始化 CTF 所需的其他所有操作(例如,将 flag 放置在已知位置) 3. (如果启用了 _Frida_) 根据安装的版本和设备架构下载正确的 `frida-server` 并启动它 4. 运行目标应用(通过 `DROIDGROUND_APP_PACKAGE_NAME` 指定的应用)。如果应用未安装,_DroidGround_ 将退出。 5. 设置 _REST APIs_、_WebSocket_ 服务器和显示流 以下是一个 `setup.sh` 脚本示例: ``` #!/usr/bin/env bash adb shell pm uninstall com.example.app # To do some cleanup echo "Sleep for 2 seconds before installing app" sleep 2 echo "Installing app..." adb install ./flag.apk # The cwd is set to the "init.d" folder, so the apk file can be accessed with the relative path echo "Install command executed" ``` 对于生产部署(在真实的 CTF 中),你可能希望预先配置好预定数量的 DroidGround 实例,或者你可能希望允许用户生成实例(带有某些限制,或者将每个团队/用户与特定实例关联)。出于这个原因,我们还添加了一个简单的 [spawner 示例](./examples/spawner)。 或者,如前所述,你可以创建一个允许通过网络请求外发 flag 的挑战,并利用 `DROIDGROUND_NUM_TEAMS` 环境变量来避免生成多个实例(这可能成本高昂)。[net-multi-step](./examples/apps/net-multi-step/) 文件夹提供了一个关于如何交付此类挑战的良好示例。 ## 💡 提示 以下是设置 Android CTF 的一些建议: - 启用 **Frida 完全模式** 时要小心,选手将拥有对设备的完全控制权(这就是为什么我们制定了如 [Frida 库](./library) 中详述的 **Frida 受限模式**)。 - 启用 **终端** 时要小心,选手将拥有对设备的完全控制权。 - 启用 **关闭** 功能时要小心。 - 如果你计划使 flag 直接在 UI 中可见,你可能需要想办法生成不同的实例(每个团队/选手一个) 在投入生产之前测试设置时,获取目标应用的 **攻击面** 可能会很有用。这是选手不应该看到的信息,因为发现和分析攻击面正是他们的工作! 因此,提供了一个可在 `/attackSurface` 访问的 `GET` 端点,并使用在启动期间随机生成的 token(需用作 `Authorization` header 的值)进行保护(因此只有系统管理员才能访问)。 如果你想在受限模式下使用自己的 Frida 脚本,只需将包含它们的文件夹绑定挂载到 Docker 容器中: ``` volumes: - :/droidground/library ``` 需要一个 `library.json` 文件(如 [library](./library/library.json) 中的那个)来指示应用程序关于可用脚本的列表。 ## 🛠 开发 让它启动并运行起来应该不会太困难,但在开始之前,你应该安装以下工具: - `frida` (仅当你启用 _Frida_ 时) - `node` (这是一个 Node 应用,你需要安装它!) - `adb` (好吧,我们依赖它与设备通信) - _JDK_ (你需要它来构建配套应用) 之后你可以直接运行以下命令: ``` git clone https://github.com/SECFORCE/droidground.git cd droidground # 不运行 scripts 进行安装 npm install --ignore-scripts # 重新构建 frida 以获取 bindings npm rebuild frida # 构建 companion app npm run companion # 获取 scrcpy npx fetch-scrcpy-server 3.1 npm run scrcpy ``` 之后你只需设置 **env** 变量,然后运行 `npm run dev` 即可大功告成。祝你开发! ## 🪪 许可证 _DroidGround_ 在 [GPL-3.0 许可证](https://github.com/SECFORCE/droidground/blob/main/LICENSE) 下发布
标签:Android CTF, Android应用安全, APK安全, CTF平台, MITM代理, 云安全监控, 云资产清单, 安全测试, 安全竞赛, 安全靶场, 应用防护, 攻击性安全, 沙箱环境, 目录枚举, 移动安全, 网络安全, 自动化攻击, 请求拦截, 越狱逃逸, 逆向工程, 隐私保护, 静态分析, 黑帽大会