Volver a actualizaciones
Nuevo releaseJul 28, 2026

droidground v1.0.11

Un campo de juegos flexible para desafíos CTF en Android.

Compartir


droidground

DroidGround


Website | Demo

En los retos CTF tradicionales, es común ocultar flags en archivos dentro 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ácilmente descargables y reversibles, 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 severamente la capacidad de crear retos realistas centrados en el tiempo de ejecución.

DroidGround está diseñado para resolver este problema.

Es una plataforma construida a medida para alojar retos de hacking móvil en Android en un entorno controlado y realista, donde los atacantes están limitados lo justo para requerir resolver los retos de la forma prevista.

Es importante destacar que los participantes pueden estar encerrados dentro del entorno de la aplicación. La modularidad de la herramienta permite establecer si el usuario puede o no abrir una shell, leer archivos arbitrarios o instalar herramientas. Todo puede configurarse para que la única forma de recuperar la flag sea comprendiendo y explotando la propia aplicación.

📋 Tabla de Contenidos

🧭 Descripción general

DroidGround permite una amplia variedad de retos de Android que de otro modo son difíciles de implementar en configuraciones CTF tradicionales. Por ejemplo, en un reto de ejecución remota de código (RCE), los jugadores podrían 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 retos pueden implicar actividades ocultas, intents de broadcast personalizados, explotación de servicios o análisis dinámico usando herramientas precargadas.

Con streaming del dispositivo en tiempo real, control detallado sobre las características, integración con Frida y scripts de configuración y reinicio personalizables, DroidGround permite a los organizadores de CTF construir retos de Android seguros, flexibles y realistas que van mucho más allá de lo que normalmente es posible.

✨ Características

DroidGround proporciona un amplio conjunto de características controladas por el servidor.

  • Pantalla del dispositivo en tiempo real (mediante scrcpy), con control opcional de ratón, táctil y teclado
  • Restablecer el estado del reto
  • Reiniciar app / Iniciar actividad / Iniciar servicio
  • Enviar intent de broadcast
  • Apagar / Reiniciar dispositivo
  • Descargar bugreport (bugreportz)
  • Scripting con Frida
    • Ejecutar desde biblioteca precargada (modo restringido)
    • Ejecutar scripts arbitrarios (modo completo)
  • Explorador de archivos
  • Acceso a terminal
  • Gestión de APK
  • Visor de Logcat
  • Servidor de exploits (si el modo equipo está habilitado)

Casi todas las características son modulares y se definen mediante variables de entorno, lo que garantiza un control preciso sobre el alcance del reto.

📸 Capturas de pantalla

Screenshot OverviewScreenshot Start Activity
Descripción generalIniciar actividad
Screenshot Frida Jailed ModeScreenshot Frida Full Mode
Modo restringido de FridaModo completo de Frida
Screenshot File BrowserScreenshot App Manager
Explorador de archivosGestor de apps
Screenshot TerminalScreenshot Logs
TerminalLogs

⚙️ 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 soportadas actualmente:

VariableDescripciónPor defecto
DROIDGROUND_BASE_PATHRuta de la aplicación web (útil para alojar en subrutas)-
DROIDGROUND_APP_PACKAGE_NAMENombre del paquete de la app objetivo-
DROIDGROUND_ADB_HOSTHost de ADBlocalhost
DROIDGROUND_ADB_PORTPuerto de ADB5037
DROIDGROUND_ADB_SERIALNúmero de serie opcional del dispositivo ADB al que conectarse-
DROIDGROUND_DEVICE_TYPEusb o networkusb
DROIDGROUND_DEVICE_HOSTIP del dispositivo Android (adb) (solo modo red)-
DROIDGROUND_DEVICE_PORTPuerto del dispositivo Android (adb) (solo modo red)-
DROIDGROUND_INIT_SCRIPTS_FOLDERCarpeta que contiene setup.sh y reset.sh/init.d
DROIDGROUND_HOSTDirección de enlace0.0.0.0
DROIDGROUND_PORTPuerto de enlace4242
DROIDGROUND_RESTART_APP_DISABLEDDeshabilitar reinicio de la appfalse
DROIDGROUND_APP_MANAGER_DISABLEDDeshabilitar gestor de appsfalse
DROIDGROUND_BUG_REPORT_DISABLEDDeshabilitar bugreportfalse
DROIDGROUND_FILE_BROWSER_DISABLEDDeshabilitar explorador de archivosfalse
DROIDGROUND_FRIDA_DISABLEDDeshabilitar soporte de Fridafalse
DROIDGROUND_FRIDA_TYPEjail o fulljail
DROIDGROUND_FRIDA_INJECTIONserver o gadgetserver
DROIDGROUND_LOGCAT_DISABLEDDeshabilitar logcatfalse
DROIDGROUND_REBOOT_ENABLEDHabilitar reiniciofalse
DROIDGROUND_SHUTDOWN_ENABLEDHabilitar apagadofalse
DROIDGROUND_START_ACTIVITY_DISABLEDDeshabilitar startActivityfalse
DROIDGROUND_START_RECEIVER_DISABLEDDeshabilitar broadcastfalse
DROIDGROUND_START_SERVICE_DISABLEDDeshabilitar startServicefalse
DROIDGROUND_TERMINAL_DISABLEDDeshabilitar terminalfalse
DROIDGROUND_RESET_DISABLEDDeshabilitar reiniciofalse
DROIDGROUND_SCRCPY_CONTROL_ENABLEDHabilitar entrada de ratón, táctil y teclado a través de la pantalla del dispositivofalse
DROIDGROUND_SCRCPY_MAX_SIZEDimensión máxima de vídeo en píxeles; 0 mantiene la resolución completa del dispositivo1280
DROIDGROUND_SCRCPY_MAX_FPSTasa de fotogramas máxima de vídeo; 0 la deja sin límite60
DROIDGROUND_SCRCPY_VIDEO_BIT_RATEBitrate de vídeo en bits por segundo4000000
DROIDGROUND_EXPLOIT_APP_DURATIONEl tiempo (en segundos) que la app de exploit estará activa10
DROIDGROUND_EXPLOIT_APP_MAX_SIZEEl tamaño máximo (en MB) de la app de exploit50
DROIDGROUND_NUM_TEAMSEl número de equipos jugando simultáneamente-
DROIDGROUND_TEAM_TOKEN_<N>El token para el enésimo equipo. Se genera automáticamente si falta-
DROIDGROUND_IP_STATICLa dirección IP estática a mostrar. Tiene prioridad sobre DROIDGROUND_IP_IFACE-
DROIDGROUND_IP_IFACELa interfaz de red para la dirección IP mostrada-
DROIDGROUND_LOGO_LINKEstablece opcionalmente el enlace al hacer clic en el logo (p. ej., tu página principal del CTF)-

Establece DROIDGROUND_SCRCPY_CONTROL_ENABLED=true y reinicia DroidGround para hacer interactiva la pantalla del dispositivo. Haz clic o toca la pantalla para enfocarla, luego haz clic, arrastra, desliza, usa múltiples puntos táctiles, desplázate con la rueda del ratón o escribe. Haz clic derecho o pulsa Escape para el botón Atrás de Android. Tab y Shift+Tab mueven el foco fuera de la pantalla. La entrada es compartida por todos los que visualizan el dispositivo, incluso en modo equipo. El valor por defecto sigue siendo una pantalla de solo visualización. La entrada de texto utiliza la inyección de teclas de Android de scrcpy, por lo que la compatibilidad de caracteres depende del mapeo de teclado del dispositivo.

La variable DROIDGROUND_IP_IFACE busca primero una coincidencia exacta y recurre a la primera interfaz que empiece por el valor proporcionado, ya que Docker solo permite especificar el prefijo de la interfaz de red dentro del contenedor.

El streaming de pantalla usa por defecto una dimensión máxima de 1280 píxeles, hasta 60 fps y 4 Mbps para reducir la carga de codificación, red y navegador. Esto sacrifica algo de detalle fino a cambio de capacidad de respuesta en la vista embebida del dispositivo. Establece DROIDGROUND_SCRCPY_MAX_SIZE=0 y DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000 para restaurar la configuración de calidad a resolución completa anterior. Para conexiones o navegadores más lentos, prueba un tamaño máximo de 1024, 30 fps y 2000000 bits por segundo. Reinicia DroidGround después de cambiar estas configuraciones.

El navegador usa WebCodecs cuando está disponible y recurre al decodificador H.264 por software en caso contrario. WebCodecs requiere un contexto seguro: usa HTTPS para despliegues remotos (localhost también funciona). HTTP simple en una IP o nombre de host remoto usa decodificación por software. Los visores lentos saltan a un fotograma clave nuevo en lugar de acumular un retraso de vídeo; unirse o recuperarse puede tardar aproximadamente un intervalo de fotograma clave (un segundo). Consulta la especificación de WebCodecs y la documentación de vídeo de scrcpy para conocer la configuración subyacente del navegador y del vídeo.

El uso de la variable DROIDGROUND_NUM_TEAMS cambia ligeramente el comportamiento de la aplicación internamente. Si esta opción está establecida:

  1. La característica del servidor de exploits se habilita, permitiendo a cada equipo usar su propio servidor de exploits (muy simple) mediante su token de equipo.
  2. El token de equipo será requerido para instalar y ejecutar apps de exploit. Cada app instalada estará vinculada a un equipo y otros equipos no podrán ejecutarla.

Esto permite compartir la misma instancia de DroidGround con múltiples equipos en retos donde la flag puede ser exfiltrada mediante una petición de red. Esto reduce masivamente los costes de despliegue de DroidGround para competiciones CTF.

Además, si el valor se establece en -1, habilitará el llamado modo Equipos Ilimitados. En este modo, un botón para generar un nuevo token de equipo estará disponible en la página Descripción general. Todas las variables DROIDGROUND_TEAM_TOKEN_<N> se ignoran si este modo está habilitado.

🧩 Casos de uso

Aquí hay algunas formas en que se puede usar DroidGround:

  1. Actividad oculta: Encontrar y lanzar una actividad no expuesta para ver la flag (la app del jugador contiene una flag ficticia).
  2. RCE: La app es vulnerable a RCE y la flag está almacenada en el dispositivo.
  3. Instrumentación con Frida: Sobrecargar un método y extraer la flag de la memoria privada usando un script.

⚙️ Uso

Se proporcionan un par de archivos Docker Compose de ejemplo en la carpeta examples. Usan apps del repositorio de ejemplos de DroidGround, que se mejorará progresivamente para mostrar todas las características clave. También son un buen punto de partida para entender cómo configurar tu propio CTF.

Al arrancar, DroidGround hace lo siguiente:

  1. Establece la conexión con adb
  2. Ejecuta el setup.sh en la carpeta especificada por DROIDGROUND_INIT_SCRIPTS_FOLDER si está presente. Este script puede usarse para instalar la app objetivo y hacer todo lo demás que sea necesario para inicializar el CTF (p. ej., colocar la flag en una ubicación conocida)
  3. (si Frida está habilitado) Descarga el frida-server correcto según la versión instalada y la arquitectura del dispositivo y lo inicia
  4. Ejecuta la app objetivo (la especificada mediante DROIDGROUND_APP_PACKAGE_NAME). Si la app no está instalada, DroidGround saldrá.
  5. Configura las REST APIs, los servidores WebSocket y el streaming de pantalla

Aquí hay un script setup.sh de ejemplo:

#!/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) quizás quieras aprovisionar un número predefinido de instancias de DroidGround de antemano o quizás quieras permitir a los usuarios crear instancias (con una limitación o tal vez asociar cada equipo/usuario con una instancia específica). Por esta razón también añadimos un sencillo ejemplo de spawner.

Alternativamente, como se mencionó anteriormente, puedes crear un reto donde la flag pueda ser exfiltrada 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 ser costoso). La carpeta net-multi-step proporciona un buen ejemplo de cómo entregar este tipo de retos.

💡 Consejos

Aquí hay algunas sugerencias para configurar tu CTF de Android:

  • Ten cuidado al habilitar el Modo completo de Frida, el jugador tendrá control total sobre el dispositivo (por eso creamos el Modo restringido de Frida como se detalla en Biblioteca de Frida).
  • Ten cuidado al habilitar el Terminal, el jugador tendrá control total sobre el dispositivo.
  • Ten cuidado al habilitar la característica de Apagado.
  • Si planeas hacer la flag directamente visible en la interfaz de usuario, quizás quieras encontrar una forma de crear diferentes instancias (una para cada equipo/jugador)

Mientras pruebas la configuración antes de pasar a producción, podría ser útil obtener la superficie de ataque de la app objetivo. ¡Esto es algo que los jugadores no deberían ver porque forma parte de su trabajo descubrir y analizar la superficie de ataque!

Por lo tanto, se proporciona un endpoint GET accesible en /attackSurface y protegido con un token (que debe usarse como valor de la cabecera Authorization) que se genera aleatoriamente durante el arranque y se imprime en los logs (por lo tanto, accesible solo por administradores de sistemas).

Si quieres usar tus propios scripts de Frida en modo restringido, solo necesitas montar la carpeta que los contiene en el contenedor Docker:

volumes:
  - <Frida library folder>:/droidground/library

Se requiere un archivo library.json (como el de 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 Node, necesitas tenerlo!)
  • adb (bueno, dependemos de él para comunicarnos con el dispositivo)
  • JDK (lo necesitas para compilar la app complementaria)

Después de eso, puedes simplemente 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 de eso, solo necesitas establecer las variables de entorno y luego ejecutar npm run dev y estarás listo para empezar. ¡Feliz modo desarrollo!

🤝 Contribuir

¡Las pull requests son bienvenidas! Por favor, abre primero un issue para discutir cambios importantes. Las ideas para nuevos flujos de trabajo de CTF o tipos de retos son especialmente apreciadas.

📚 Créditos

Desarrollado por Angelo Delicato @SECFORCE.

La sección del servidor depende en gran medida del increíble trabajo realizado por @yume-chan, probablemente esta app no existiría si no fuera por su increíble trabajo.

La app complementaria está basada en gran medida en el servidor aya, que funciona de la misma manera que el servidor scrcpy. Se pueden encontrar más detalles en el README específico.

🪪 Licencia

DroidGround se publica bajo la LICENCIA GPL-3.0

Categorías