
droidground v1.0.14
一个灵活的 Android CTF 挑战游乐场。
DroidGround
在传统的 CTF 挑战中,通常会将 flag 隐藏在系统文件中,要求攻击者利用漏洞来获取它们。然而,在 Android 世界中,这种方法效果不佳。APK 文件很容易被下载和逆向,因此将 flag 放在设备上通常使其变得轻而易举,可以通过静态分析或模拟器技巧来提取。这严重限制了创建逼真的、以运行时为重点的挑战的能力。
DroidGround 正是为解决这一问题而设计的。
它是一个定制构建的平台,用于在受控且逼真的环境中托管 Android 移动黑客挑战,其中攻击者受到恰到好处的限制,从而必须以预期的方式解决挑战。
重要的是,参与者可能被限制在应用环境内。该工具的模块化设计允许设置用户是否可以启动 shell、读取任意文件或侧载工具。一切都可以配置为:获取 flag 的唯一途径就是理解和利用应用本身。
📋 目录
🧭 概述
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 服务器(如果启用了团队模式)
几乎所有功能都是模块化的,并通过环境变量定义,确保对挑战范围进行精确控制。
📸 截图
![]() | ![]() |
|---|---|
| 概述 | 启动 Activity |
![]() | ![]() |
| Frida 受限模式 | Frida 完整模式 |
![]() | ![]() |
| 文件浏览器 | 应用管理器 |
![]() | ![]() |
| 终端 | 日志 |
⚙️ 配置
根目录中的 .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_SCRCPY_CONTROL_ENABLED | 通过设备屏幕启用鼠标、触摸和键盘输入 | false |
DROIDGROUND_SCRCPY_MAX_SIZE | 最大视频尺寸(像素);0 保持设备完整分辨率 | 1280 |
DROIDGROUND_SCRCPY_MAX_FPS | 最大视频帧率;0 表示不限制 | 60 |
DROIDGROUND_SCRCPY_VIDEO_BIT_RATE | 视频比特率(比特每秒) | 4000000 |
DROIDGROUND_EXPLOIT_APP_DURATION | Exploit 应用处于活动状态的时间(秒) | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | Exploit 应用的最大大小(MB) | 50 |
DROIDGROUND_NUM_TEAMS | 同时参与的团队数量 | - |
DROIDGROUND_TEAM_TOKEN_<N> | 第 n 个团队的令牌。如果缺失则自动生成 | - |
DROIDGROUND_IP_STATIC | 要显示的静态 IP 地址。它优先于 DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | 用于显示 IP 地址的网络接口 | - |
DROIDGROUND_LOGO_LINK | 可选设置 logo 点击跳转链接(例如,你的 CTF 主页) | - |
设置 DROIDGROUND_SCRCPY_CONTROL_ENABLED=true 并重启 DroidGround,使设备屏幕可交互。点击或轻触屏幕以使其获得焦点,然后可以点击、拖动、滑动、使用多点触控、用鼠标滚轮滚动或输入。右键单击或按 Escape 键执行 Android 返回操作。Tab 和 Shift+Tab 将焦点移出屏幕。输入由所有查看设备的人共享,包括在团队模式下。默认仍为仅查看屏幕。文本输入使用 scrcpy 的 Android 按键注入,因此字符支持取决于设备的键盘映射。
DROIDGROUND_IP_IFACE 首先查找精确匹配,然后回退到以所提供值_开头_的第一个接口,因为 Docker 只允许在容器内指定网络接口前缀。
屏幕流默认最大尺寸为 1280 像素,最高 60 fps,4 Mbps,以减少编码、网络和浏览器的工作量。这在嵌入式设备视图中以牺牲一些精细细节来换取响应速度。设置 DROIDGROUND_SCRCPY_MAX_SIZE=0 和 DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000 可恢复之前的全分辨率质量设置。对于较慢的连接或浏览器,请尝试最大尺寸 1024、30 fps 和 2000000 比特每秒。更改这些设置后请重启 DroidGround。
浏览器在可用时使用 WebCodecs,否则回退到软件 H.264 解码器。WebCodecs 需要安全上下文:远程部署请使用 HTTPS(localhost 也可以)。在远程 IP 或主机名上使用纯 HTTP 将使用软件解码。慢速查看器会跳转到新的关键帧,而不是累积视频积压;加入或恢复可能需要大约一个关键帧间隔(一秒)。有关底层浏览器和视频设置,请参阅 WebCodecs 规范 和 scrcpy 视频文档。
使用 DROIDGROUND_NUM_TEAMS 变量会在底层稍微改变应用的行为。如果设置了此选项:
- 启用 exploit 服务器功能,允许每个团队通过其 团队令牌 使用自己的(非常简单的)exploit 服务器。
- 安装和运行 exploit 应用将需要团队令牌。每个安装的应用都将绑定到一个团队,其他团队将无法运行它。
这允许在可以通过网络请求窃取 flag 的挑战中,与多个团队共享同一个 DroidGround 实例。这大幅降低了 CTF 竞赛中 DroidGround 的部署成本。
此外,如果该值设置为 -1,将启用所谓的无限团队模式。在此模式下,_概述_页面中将提供一个生成新 团队令牌 的按钮。如果启用了此模式,所有 DROIDGROUND_TEAM_TOKEN_<N> 变量都将被忽略。
🧩 使用场景
以下是 DroidGround 的一些使用方式:
- 隐藏 Activity:找到并启动一个未暴露的 Activity 以查看 flag(玩家的应用包含一个虚拟 flag)。
- RCE:应用易受 RCE 攻击,flag 存储在设备上。
- Frida 插桩:使用脚本重载方法并从私有内存中提取 flag。
⚙️ 使用方法
examples 文件夹中提供了几个示例 Docker Compose 文件。它们使用来自 DroidGround 示例仓库 的应用,这些应用将逐步增强以展示所有关键功能。它们也是了解如何设置自己的 CTF 的良好起点。
启动时 DroidGround 会执行以下操作:
- 使用
adb建立连接 - 如果存在,运行
DROIDGROUND_INIT_SCRIPTS_FOLDER指定文件夹中的setup.sh。此脚本可用于安装目标应用并执行初始化 CTF 所需的其他所有操作(例如将 flag 放置在已知位置) - (如果启用了 Frida)根据安装的版本和设备的架构下载正确的
frida-server并启动它 - 运行目标应用(通过
DROIDGROUND_APP_PACKAGE_NAME指定的应用)。如果应用未安装,DroidGround 将退出。 - 设置 REST API、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 示例。
或者,如前所述,你可以创建一个可以通过网络请求窃取 flag 的挑战,并利用 DROIDGROUND_NUM_TEAMS 环境变量来避免生成多个实例(这可能成本高昂)。net-multi-step 文件夹提供了一个很好的示例,说明如何交付此类挑战。
💡 提示
以下是一些设置 Android CTF 的建议:
- 启用 Frida 完整模式时要小心,玩家将拥有对设备的完全控制权(这就是我们制作 Frida 受限模式的原因,详见 Frida 库)。
- 启用终端时要小心,玩家将拥有对设备的完全控制权。
- 启用关机功能时要小心。
- 如果你计划让 flag 直接在 UI 中可见,你可能需要找到一种生成不同实例的方法(每个团队/玩家一个)
在生产环境部署之前测试设置时,获取目标应用的攻击面可能会很有用。这是玩家不应该看到的内容,因为发现和分析攻击面是他们工作的一部分!
因此,提供了一个可通过 /attackSurface 访问的 GET 端点,并使用在启动期间随机生成并打印在日志中的令牌(需要用作 Authorization 头的值)进行保护(因此只有系统管理员可以访问)。
如果你想在受限模式下使用自己的 Frida 脚本,只需将包含它们的文件夹绑定挂载到 Docker 容器中:
volumes:
- <Frida library folder>:/droidground/library
需要一个 library.json 文件(如 library 中的文件)来指示应用可用脚本的列表。
🛠 开发
让它运行起来应该不会太难,但在开始之前,你应该安装以下工具:
frida(仅在你启用 Frida 时需要)node(这是一个 Node 应用,你需要安装它!)adb(嗯,我们依赖它与设备通信)- JDK(你需要它来构建配套应用)
之后,你只需运行以下命令:
git clone https://github.com/SECFORCE/droidground.git
cd droidground
# Install without running scripts
npm install --ignore-scripts
# Rebuild frida to get the bindings
npm rebuild frida
# Build companion app
npm run companion
# Get scrcpy
npm run scrcpy
之后,你只需设置 env 变量,然后运行 npm run dev,就可以开始了。开发模式愉快!
🤝 贡献
欢迎提交 Pull Request!请先开一个 issue 讨论重大更改。特别欢迎关于新 CTF 工作流或挑战类型的想法。
📚 致谢
由 Angelo Delicato @SECFORCE 开发。
server 部分严重依赖于 @yume-chan 所做的出色工作,如果没有他的出色工作,这个应用可能不会存在。
companion 应用很大程度上基于 aya server,其工作方式与 scrcpy server 相同。更多细节可以在特定的 README 中找到。
🪪 许可证
DroidGround 在 GPL-3.0 许可证 下发布







