
droidground v1.0.14
Гибкая площадка для Android CTF-задач.
DroidGround
В традиционных CTF-задачах принято прятать флаги в файлах на системе, заставляя атакующих эксплуатировать уязвимости для их извлечения. Однако в мире Android такой подход плохо работает. APK-файлы легко скачиваются и реверсируются, поэтому размещение флага на устройстве обычно делает его извлечение тривиальным с помощью статического анализа или трюков с эмулятором. Это серьёзно ограничивает возможность создавать реалистичные задачи, ориентированные на время выполнения.
DroidGround создан для решения этой проблемы.
Это специально разработанная платформа для проведения задач по взлому Android-приложений в контролируемой и реалистичной среде, где атакующие ограничены ровно настолько, чтобы решать задачи предполагаемым способом.
Что важно, участники могут быть заперты внутри среды приложения. Модульность инструмента позволяет настроить, может ли пользователь запустить шелл, читать произвольные файлы или устанавливать сторонние инструменты. Всё можно настроить так, чтобы единственным способом получить флаг было понимание и эксплуатация самого приложения.
📋 Содержание
- 🧭 Обзор
- ✨ Возможности
- 📸 Скриншоты
- ⚙️ Конфигурация
- 🧩 Сценарии использования
- ⚙️ Использование
- 💡 Советы
- 🛠 Разработка
- 🤝 Участие в разработке
- 📚 Благодарности
- 🪪 Лицензия
🧭 Обзор
DroidGround позволяет реализовать широкий спектр задач для Android, которые иначе сложно реализовать в традиционных CTF-сетапах. Например, в задаче на удалённое выполнение кода (RCE) игроки могут получить APK для локального анализа. Обнаружив уязвимость, они могут разработать скрипт Frida и запустить его через DroidGround на реальном целевом устройстве, чтобы извлечь флаг из внутреннего хранилища. Другие типы задач могут включать скрытые активности, пользовательские broadcast-интенты, эксплуатацию сервисов или динамический анализ с использованием предзагруженных инструментов.
Благодаря потоковой передаче экрана устройства в реальном времени, тонкой настройке функций, интеграции с Frida и настраиваемым скриптам установки и сброса, DroidGround даёт организаторам CTF возможность создавать безопасные, гибкие и реалистичные задачи для Android, выходящие далеко за рамки обычного.
✨ Возможности
DroidGround предоставляет богатый набор функций, управляемых с сервера.
- Экран устройства в реальном времени (через
scrcpy), с опциональным управлением мышью, касаниями и клавиатурой - Сброс состояния задачи
- Перезапуск приложения / Запуск активности / Запуск сервиса
- Отправка broadcast-интента
- Выключение / Перезагрузка устройства
- Скачивание bugreport (bugreportz)
- Скриптинг Frida
- Запуск из предзагруженной библиотеки (режим jail)
- Запуск произвольных скриптов (полный режим)
- Файловый браузер
- Доступ к терминалу
- Управление APK
- Просмотр Logcat
- Сервер эксплойтов (если включён командный режим)
Почти все функции модульные и определяются через переменные окружения, что обеспечивает точный контроль над рамками задачи.
📸 Скриншоты
![]() | ![]() |
|---|---|
| Обзор | Запуск активности |
![]() | ![]() |
| Режим Frida Jail | Полный режим Frida |
![]() | ![]() |
| Файловый браузер | Менеджер приложений |
![]() | ![]() |
| Терминал | Логи |
⚙️ Конфигурация
Файл .env.sample в корневой директории — хорошая отправная точка. Ниже приведён полный список всех поддерживаемых на данный момент переменных окружения:
| Переменная | Описание | По умолчанию |
|---|---|---|
DROIDGROUND_BASE_PATH | Путь веб-приложения (полезно для размещения на подпутях) | - |
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 | IP-адрес Android-устройства (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 | Отключить broadcast | 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 | Время (в секундах), в течение которого эксплойт-приложение будет активно | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | Максимальный размер (в МБ) эксплойт-приложения | 50 |
DROIDGROUND_NUM_TEAMS | Количество команд, играющих одновременно | - |
DROIDGROUND_TEAM_TOKEN_<N> | Токен для n-й команды. Генерируется автоматически при отсутствии | - |
DROIDGROUND_IP_STATIC | Статический IP-адрес для отображения. Имеет приоритет над DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | Сетевой интерфейс для отображаемого IP-адреса | - |
DROIDGROUND_LOGO_LINK | Опционально задаёт ссылку при клике на логотип (например, главную страницу вашего CTF) | - |
Установите DROIDGROUND_SCRCPY_CONTROL_ENABLED=true и перезапустите DroidGround, чтобы сделать экран устройства интерактивным. Кликните или коснитесь экрана, чтобы сфокусировать его, затем кликайте, перетаскивайте, свайпайте, используйте несколько точек касания, прокручивайте колесом мыши или вводите текст. Правый клик или Escape — кнопка «Назад» в Android. Tab и Shift+Tab перемещают фокус за пределы экрана. Ввод разделяется всеми, кто просматривает устройство, в том числе в командном режиме. По умолчанию экран остаётся доступным только для просмотра. Ввод текста использует инъекцию клавиш Android от scrcpy, поэтому поддержка символов зависит от раскладки клавиатуры устройства.
DROIDGROUND_IP_IFACE сначала ищет точное совпадение и при неудаче переходит к первому интерфейсу, который начинается с указанного значения, поскольку Docker позволяет указать внутри контейнера только префикс сетевого интерфейса.
Потоковая передача экрана по умолчанию использует максимальный размер 1280 пикселей, до 60 fps и 4 Мбит/с, чтобы снизить нагрузку на кодирование, сеть и браузер. Это идёт на компромисс между детализацией и отзывчивостью во встроенном представлении устройства. Установите DROIDGROUND_SCRCPY_MAX_SIZE=0 и DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000, чтобы вернуть прежние настройки качества с полным разрешением. Для медленных соединений или браузеров попробуйте максимальный размер 1024, 30 fps и 2000000 бит в секунду. Перезапустите DroidGround после изменения этих настроек.
Браузер использует WebCodecs, когда он доступен, и в противном случае переключается на программный декодер H.264. WebCodecs требует защищённого контекста: используйте HTTPS для удалённых развёртываний (localhost также подходит). Обычный HTTP на удалённом IP или имени хоста использует программное декодирование. Медленные зрители пропускают кадры до свежего ключевого кадра вместо накопления отставания видео; подключение или восстановление может занять около одного интервала ключевых кадров (одна секунда). См. спецификацию WebCodecs и документацию по видео scrcpy для получения информации о базовых настройках браузера и видео.
Использование переменной DROIDGROUND_NUM_TEAMS немного меняет поведение приложения под капотом. Если эта опция задана:
- Включается функция сервера эксплойтов, позволяя каждой команде использовать свой собственный (очень простой) сервер эксплойтов через свой токен команды.
- Токен команды будет обязателен для установки и запуска эксплойт-приложений. Каждое установленное приложение будет привязано к команде, и другие команды не смогут его запустить.
Это позволяет использовать один и тот же экземпляр DroidGround несколькими командами в задачах, где флаг можно вынести через сетевой запрос. Это значительно снижает затраты на развёртывание DroidGround для CTF-соревнований.
Кроме того, если значение установлено в -1, включается так называемый режим Unlimited Teams. В этом режиме на странице Обзор появится кнопка для генерации нового токена команды. Все переменные DROIDGROUND_TEAM_TOKEN_<N> игнорируются, если этот режим включён.
🧩 Сценарии использования
Вот несколько способов использования DroidGround:
- Скрытая активность: найдите и запустите неэкспортируемую активность, чтобы увидеть флаг (приложение игрока содержит фиктивный флаг).
- RCE: приложение уязвимо к RCE, а флаг хранится на устройстве.
- Инструментирование Frida: перегрузите метод и извлеките флаг из приватной памяти с помощью скрипта.
⚙️ Использование
Несколько примеров файлов Docker Compose предоставлены в папке examples. Они используют приложения из репозитория примеров DroidGround, который будет постепенно дополняться для демонстрации всех ключевых функций. Они также являются хорошей отправной точкой для понимания того, как настроить собственный CTF.
При загрузке DroidGround выполняет следующее:
- Устанавливает соединение с
adb - Запускает
setup.shв папке, указанной вDROIDGROUND_INIT_SCRIPTS_FOLDER, если он присутствует. Этот скрипт можно использовать для установки целевого приложения и всего остального, что нужно для инициализации CTF (например, размещения флага в известном месте) - (если 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 или разрешить пользователям создавать экземпляры (с ограничением или, возможно, связав каждую команду/пользователя с конкретным экземпляром). По этой причине мы также добавили простой пример спавнера.
Как уже упоминалось, в качестве альтернативы вы можете создать задачу, где флаг можно вынести через сетевой запрос, и использовать переменную окружения DROIDGROUND_NUM_TEAMS, чтобы избежать создания множества экземпляров (что может быть дорого). Папка net-multi-step предоставляет хороший пример того, как реализовать такие задачи.
💡 Советы
Вот несколько рекомендаций по настройке вашего Android CTF:
- Будьте осторожны при включении Frida Full Mode — игрок получит полный контроль над устройством (именно поэтому мы сделали Frida Jail Mode, как описано в Библиотеке Frida).
- Будьте осторожны при включении Терминала — игрок получит полный контроль над устройством.
- Будьте осторожны при включении функции Выключение.
- Если вы планируете сделать флаг видимым прямо в UI, вам, возможно, стоит найти способ создавать разные экземпляры (по одному на команду/игрока)
При тестировании сетапа перед выходом в продакшн может быть полезно получить поверхность атаки целевого приложения. Это то, что игроки не должны видеть, поскольку обнаружение и анализ поверхности атаки — часть их работы!
Поэтому предоставляется endpoint GET, доступный по адресу /attackSurface, защищённый токеном (который нужно использовать как значение заголовка Authorization), случайно генерируемым при загрузке и выводимым в логи (следовательно, доступным только системным администраторам).
Если вы хотите использовать свои собственные скрипты Frida в режиме jail, вам просто нужно примонтировать папку, содержащую их, в Docker-контейнер:
volumes:
- <Frida library folder>:/droidground/library
Файл library.json (как в library) необходим, чтобы сообщить приложению список доступных скриптов.
🛠 Разработка
Запустить всё это не должно быть слишком сложно, но перед началом у вас должны быть установлены следующие инструменты:
frida(только если вы включаете Frida)node(это Node-приложение, он вам нужен!)adb(ну, мы полагаемся на него для связи с устройством)- JDK (нужен для сборки companion-приложения)
После этого вы можете просто выполнить следующее:
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







