
droidground v1.0.11
Un campo de juegos flexible para desafíos CTF en Android.
DroidGround
En los desafíos CTF tradicionales, es común ocultar flags en archivos de un sistema, lo que obliga a los atacantes a explotar vulnerabilidades para recuperarlas. Sin embargo, en el mundo de Android, este enfoque no funciona bien. Los archivos APK son fáciles de descargar y de aplicar ingeniería inversa, por lo que colocar una flag en el dispositivo normalmente hace que sea trivial extraerla mediante análisis estático o trucos de emulador. Esto limita gravemente la capacidad de crear desafíos realistas centrados en el tiempo de ejecución.
DroidGround está diseñado para resolver este problema.
Es una plataforma creada a medida para alojar desafíos de hacking móvil Android en un entorno controlado y realista, donde los atacantes están restringidos lo justo para que tengan que resolver los desafíos de la forma prevista.
Es importante destacar que los participantes pueden estar enjaulados dentro del entorno de la aplicación. La modularidad de la herramienta permite configurar si el usuario puede o no abrir un shell, leer archivos arbitrarios o cargar herramientas externas. Todo puede configurarse de modo que la única forma de recuperar la flag sea comprendiendo y explotando la propia aplicación.
📋 Tabla de contenidos
- 🧭 Descripción general
- ✨ Características
- 📸 Capturas de pantalla
- ⚙️ Configuración
- 🧩 Casos de uso
- ⚙️ Uso
- 💡 Consejos
- 🛠 Desarrollo
- 🤝 Contribuciones
- 📚 Créditos
- 🪪 Licencia
🧭 Descripción general
DroidGround permite una gran variedad de desafíos Android que de otro modo serían difíciles de implementar en configuraciones CTF tradicionales. Por ejemplo, en un desafío de ejecución remota de código (RCE), los jugadores pueden recibir un APK para su análisis local. Tras descubrir una vulnerabilidad, pueden desarrollar un script de Frida y ejecutarlo a través de DroidGround en el dispositivo objetivo real para extraer la flag del almacenamiento interno. Otros tipos de desafíos pueden implicar actividades ocultas, intents de broadcast personalizados, explotación de servicios o análisis dinámico mediante herramientas precargadas.
Con transmisión del dispositivo en tiempo real, control granular de las funciones, integración con Frida y scripts de configuración y restablecimiento personalizables, DroidGround permite a los organizadores de CTF crear desafíos Android seguros, flexibles y realistas que van mucho más allá de lo que normalmente es posible.
✨ Características
DroidGround ofrece un amplio conjunto de funciones controladas por el servidor.
- Pantalla del dispositivo en tiempo real (vía
scrcpy) - Restablecer el estado del desafío
- Reiniciar app / Iniciar actividad / Iniciar servicio
- Enviar intent de broadcast
- Apagar / Reiniciar el dispositivo
- Descargar bugreport (bugreportz)
- Scripting con Frida
- Ejecutar desde la biblioteca precargada (modo enjaulado)
- Ejecutar scripts arbitrarios (modo completo)
- Explorador de archivos
- Acceso a terminal
- Gestión de APK
- Visor de logcat
- Servidor de exploit (si el modo por equipos está habilitado)
Casi todas las funciones son modulares y se definen mediante variables de entorno, lo que garantiza un control preciso sobre el alcance del desafío.
📸 Capturas de pantalla
![]() | ![]() |
|---|---|
| Descripción general | Iniciar actividad |
![]() | ![]() |
| Modo Frida enjaulado | Modo Frida completo |
![]() | ![]() |
| Explorador de archivos | Gestor de apps |
![]() | ![]() |
| Terminal | Registros |
⚙️ Configuración
El archivo .env.sample en el directorio raíz es un buen punto de partida. Esta es la lista completa de todas las variables de entorno actualmente soportadas:
| Variable | Descripción | Default |
|---|---|---|
DROIDGROUND_BASE_PATH | Ruta de la aplicación web (útil para alojar en subrutas) | - |
DROIDGROUND_APP_PACKAGE_NAME | Nombre del paquete de la app objetivo | - |
DROIDGROUND_ADB_HOST | Host de ADB | localhost |
DROIDGROUND_ADB_PORT | Puerto de ADB | 5037 |
DROIDGROUND_ADB_SERIAL | Serial opcional del dispositivo ADB al que conectarse | - |
DROIDGROUND_DEVICE_TYPE | usb o network | usb |
DROIDGROUND_DEVICE_HOST | IP del dispositivo Android (adb) (solo modo red) | - |
DROIDGROUND_DEVICE_PORT | Puerto del dispositivo Android (adb) (solo modo red) | - |
DROIDGROUND_INIT_SCRIPTS_FOLDER | Carpeta que contiene setup.sh y reset.sh | /init.d |
DROIDGROUND_HOST | Dirección de enlace | 0.0.0.0 |
DROIDGROUND_PORT | Puerto de enlace | 4242 |
DROIDGROUND_RESTART_APP_DISABLED | Deshabilitar el reinicio de la app | false |
DROIDGROUND_APP_MANAGER_DISABLED | Deshabilitar el gestor de apps | false |
DROIDGROUND_BUG_REPORT_DISABLED | Deshabilitar el bugreport | false |
DROIDGROUND_FILE_BROWSER_DISABLED | Deshabilitar el explorador de archivos | false |
DROIDGROUND_FRIDA_DISABLED | Deshabilitar el soporte de Frida | false |
DROIDGROUND_FRIDA_TYPE | jail o full | jail |
DROIDGROUND_FRIDA_INJECTION | server o gadget | server |
DROIDGROUND_LOGCAT_DISABLED | Deshabilitar logcat | false |
DROIDGROUND_REBOOT_ENABLED | Habilitar el reinicio | false |
DROIDGROUND_SHUTDOWN_ENABLED | Habilitar el apagado | false |
DROIDGROUND_START_ACTIVITY_DISABLED | Deshabilitar startActivity | false |
DROIDGROUND_START_RECEIVER_DISABLED | Deshabilitar broadcast | false |
DROIDGROUND_START_SERVICE_DISABLED | Deshabilitar startService | false |
DROIDGROUND_TERMINAL_DISABLED | Deshabilitar la terminal | false |
DROIDGROUND_RESET_DISABLED | Deshabilitar el restablecimiento | false |
DROIDGROUND_EXPLOIT_APP_DURATION | El tiempo (en segundos) durante el cual la app de exploit estará activa | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | El tamaño máximo (en MB) de la app de exploit | 50 |
DROIDGROUND_NUM_TEAMS | El número de equipos jugando simultáneamente | - |
DROIDGROUND_TEAM_TOKEN_<N> | El token para el equipo N. Se genera automáticamente si falta | - |
DROIDGROUND_IP_STATIC | La dirección IP estática a mostrar. Tiene prioridad sobre DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | La interfaz de red para la dirección IP mostrada | - |
DROIDGROUND_LOGO_LINK | Opcionalmente, establece el enlace de clic del logotipo (p. ej., la página principal de tu CTF) | - |
DROIDGROUND_IP_IFACE busca primero una coincidencia exacta y, si no la encuentra, utiliza la primera interfaz que comience con el valor proporcionado, ya que Docker solo permite especificar el prefijo de la interfaz de red dentro del contenedor.
El uso de la variable DROIDGROUND_NUM_TEAMS cambia ligeramente el comportamiento interno de la aplicación. Si esta opción está configurada:
- La función de servidor de exploit está habilitada, lo que permite a cada equipo usar su propio servidor de exploit (muy simple) mediante su token de equipo.
- El token de equipo será requerido para instalar y ejecutar apps de exploit. Cada app instalada estará vinculada a un equipo y los demás equipos no podrán ejecutarla.
Esto permite compartir la misma instancia de DroidGround con varios equipos en desafíos donde la flag se puede exfiltrar mediante una petición de red. Esto reduce masivamente los costes de despliegue de DroidGround en competiciones CTF.
Además, si el valor se establece en -1, se habilitará el llamado modo Unlimited Teams (equipos ilimitados). En este modo, habrá un botón para generar un nuevo token de equipo disponible en la página de Overview. Todas las variables DROIDGROUND_TEAM_TOKEN_<N> se ignoran si este modo está habilitado.
🧩 Casos de uso
Estas son algunas formas en las que se puede usar DroidGround:
- Actividad oculta: Encuentra y lanza una actividad no expuesta para ver la flag (la app del jugador contiene una flag ficticia).
- RCE: La app es vulnerable a RCE y la flag está almacenada en el dispositivo.
- Instrumentación con Frida: Sobrecarga un método y extrae la flag de la memoria privada mediante un script.
⚙️ Uso
Se proporcionan un par de archivos de ejemplo de Docker Compose en la carpeta examples. Utilizan apps del repositorio de muestras de DroidGround, que se irá mejorando progresivamente para mostrar todas las funciones clave. También son un buen punto de partida para entender cómo configurar tu propio CTF.
Al arrancar, DroidGround hace lo siguiente:
- Establece la conexión con
adb - Ejecuta el script
setup.shde la carpeta especificada porDROIDGROUND_INIT_SCRIPTS_FOLDERsi existe. Este script se puede usar para instalar la app objetivo y hacer todo lo demás necesario para inicializar el CTF (p. ej., colocar la flag en una ubicación conocida) - (si Frida está habilitado) Descarga el
frida-servercorrecto según la versión instalada y la arquitectura del dispositivo, y lo inicia - Ejecuta la app objetivo (la especificada mediante
DROIDGROUND_APP_PACKAGE_NAME). Si la app no está instalada, DroidGround se cerrará. - Configura las REST APIs, los servidores WebSocket y la transmisión de pantalla
Este es un ejemplo de script 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"
Para un despliegue en producción (en un CTF real), es posible que quieras aprovisionar de antemano un número predefinido de instancias de DroidGround, o permitir que los usuarios creen instancias (con una limitación o quizás asociando cada equipo/usuario con una instancia específica). Por esta razón, también añadimos un ejemplo de spawner sencillo.
Alternativamente, como se mencionó anteriormente, puedes crear un desafío donde la flag se pueda exfiltrar mediante una petición de red y aprovechar la variable de entorno DROIDGROUND_NUM_TEAMS para evitar crear múltiples instancias (lo que podría resultar costoso). La carpeta net-multi-step proporciona un buen ejemplo de cómo plantear este tipo de desafíos.
💡 Consejos
Estas son algunas sugerencias para configurar tu CTF de Android:
- Ten cuidado al habilitar el Modo Frida Completo: el jugador tendrá control total sobre el dispositivo (por eso creamos el Modo Frida Enjaulado, como se detalla en Frida Library).
- Ten cuidado al habilitar la Terminal: el jugador tendrá control total sobre el dispositivo.
- Ten cuidado al habilitar la función de Apagado.
- Si planeas hacer que la flag sea directamente visible en la interfaz de usuario, quizás quieras encontrar una forma de crear diferentes instancias (una para cada equipo/jugador).
Al probar la configuración antes de pasar a producción, puede ser útil obtener la superficie de ataque de la app objetivo. ¡Esto es algo que los jugadores no deberían ver, porque descubrir y analizar la superficie de ataque es parte de su trabajo!
Por lo tanto, se proporciona un endpoint GET accesible en /attackSurface y protegido con un token (que debe utilizarse como valor del encabezado Authorization), el cual se genera aleatoriamente durante el arranque y se imprime en los registros (por lo tanto, solo accesible para los administradores del sistema).
Si quieres usar tus propios scripts de Frida en modo enjaulado, solo necesitas montar (bind-mount) la carpeta que los contiene dentro del contenedor Docker:
volumes:
- <Frida library folder>:/droidground/library
Se requiere un archivo library.json (como el de la library) para indicar a la aplicación la lista de scripts disponibles.
🛠 Desarrollo
Ponerlo en marcha no debería ser demasiado difícil, pero antes de empezar deberías tener instaladas las siguientes herramientas:
frida(solo si habilitas Frida)node(es una app de Node, ¡la necesitas!)adb(bueno, dependemos de él para comunicarnos con el dispositivo)- JDK (lo necesitas para compilar la app complementaria)
Después de eso, simplemente puedes ejecutar lo siguiente:
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
Después, solo necesitas establecer las variables de entorno y luego ejecutar npm run dev, y listo. ¡Feliz modo de desarrollo!
🤝 Contribuciones
¡Las pull requests son bienvenidas! Por favor, abre primero un issue para discutir los cambios importantes. Las ideas para nuevos flujos de trabajo CTF o tipos de desafíos son especialmente apreciadas.
📚 Créditos
Desarrollado por Angelo Delicato @SECFORCE.
La sección del servidor depende en gran medida del increíble trabajo de @yume-chan; probablemente esta app no existiría si no fuera por su asombroso trabajo.
La app complementaria se basa en gran medida en el aya server, que funciona de la misma manera que el scrcpy server. Se pueden encontrar más detalles en el README específico.
🪪 Licencia
DroidGround se publica bajo la LICENCIA GPL-3.0.







