
droidground v1.0.11
Un terrain de jeu flexible pour les défis CTF Android.
DroidGround
Dans les challenges CTF traditionnels, il est courant de cacher les flags dans des fichiers sur un système, obligeant les attaquants à exploiter des vulnérabilités pour les récupérer. Cependant, dans le monde Android, cette approche ne fonctionne pas bien. Les fichiers APK sont facilement téléchargeables et réversibles, donc placer un flag sur l'appareil le rend généralement trivial à extraire via analyse statique ou astuces d'émulateur. Cela limite sévèrement la capacité à créer des challenges réalistes axés sur l'exécution.
DroidGround est conçu pour résoudre ce problème.
C'est une plateforme sur mesure pour héberger des challenges de hacking mobile Android dans un environnement contrôlé et réaliste, où les attaquants sont suffisamment contraints pour devoir résoudre les challenges de la manière prévue.
Plus important encore, les participants peuvent être enfermés dans l'environnement de l'application. La modularité de l'outil permet de définir si l'utilisateur peut ou non lancer un shell, lire des fichiers arbitraires ou charger des outils. Tout peut être configuré pour que la seule façon de récupérer le flag soit de comprendre et d'exploiter l'application elle-même.
📋 Table des matières
- 🧭 Vue d'ensemble
- ✨ Fonctionnalités
- 📸 Captures d'écran
- ⚙️ Configuration
- 🧩 Cas d'usage
- ⚙️ Utilisation
- 💡 Astuces
- 🛠 Développement
- 🤝 Contribution
- 📚 Crédits
- 🪪 Licence
🧭 Vue d'ensemble
DroidGround permet une grande variété de challenges Android qui sont autrement difficiles à mettre en œuvre dans les configurations CTF traditionnelles. Par exemple, dans un challenge d'exécution de code à distance (RCE), les joueurs peuvent recevoir un APK pour analyse locale. Après avoir découvert une vulnérabilité, ils peuvent développer un script Frida et l'exécuter via DroidGround sur l'appareil cible réel pour extraire le flag du stockage interne. D'autres types de challenges peuvent impliquer des activités cachées, des intents de diffusion personnalisés, l'exploitation de services ou l'analyse dynamique à l'aide d'outils préchargés.
Avec la diffusion en temps réel de l'appareil, un contrôle fin des fonctionnalités, l'intégration de Frida et des scripts de configuration et de réinitialisation personnalisables, DroidGround permet aux organisateurs de CTF de créer des challenges Android sécurisés, flexibles et réalistes qui vont bien au-delà de ce qui est habituellement possible.
✨ Fonctionnalités
DroidGround fournit un riche ensemble de fonctionnalités contrôlées par le serveur.
- Écran de l'appareil en temps réel (via
scrcpy), avec contrôle optionnel de la souris, du tactile et du clavier - Réinitialiser l'état du challenge
- Redémarrer l'application / Démarrer une activité / Démarrer un service
- Envoyer un intent de diffusion
- Éteindre / Redémarrer l'appareil
- Télécharger le rapport de bug (bugreportz)
- Scripting Frida
- Exécuter depuis la bibliothèque préchargée (mode jail)
- Exécuter des scripts arbitraires (mode complet)
- Navigateur de fichiers
- Accès au terminal
- Gestion des APK
- Visionneuse Logcat
- Serveur d'exploit (si le mode équipe est activé)
Presque toutes les fonctionnalités sont modulaires et définies via des variables d'environnement, garantissant un contrôle précis de la portée du challenge.
📸 Captures d'écran
![]() | ![]() |
|---|---|
| Vue d'ensemble | Démarrer une activité |
![]() | ![]() |
| Frida mode jail | Frida mode complet |
![]() | ![]() |
| Navigateur de fichiers | Gestionnaire d'applications |
![]() | ![]() |
| Terminal | Journaux |
⚙️ Configuration
Le fichier .env.sample dans le répertoire racine est un bon point de départ. Voici la liste complète de toutes les variables d'environnement actuellement prises en charge :
| Variable | Description | Défaut |
|---|---|---|
DROIDGROUND_BASE_PATH | Chemin de l'application web (utile pour l'hébergement sur des sous-chemins) | - |
DROIDGROUND_APP_PACKAGE_NAME | Nom du package de l'application cible | - |
DROIDGROUND_ADB_HOST | Hôte ADB | localhost |
DROIDGROUND_ADB_PORT | Port ADB | 5037 |
DROIDGROUND_ADB_SERIAL | Numéro de série optionnel de l'appareil ADB auquel se connecter | - |
DROIDGROUND_DEVICE_TYPE | usb ou network | usb |
DROIDGROUND_DEVICE_HOST | IP de l'appareil Android (adb) (mode réseau uniquement) | - |
DROIDGROUND_DEVICE_PORT | port de l'appareil Android (adb) (mode réseau uniquement) | - |
DROIDGROUND_INIT_SCRIPTS_FOLDER | Dossier contenant setup.sh et reset.sh | /init.d |
DROIDGROUND_HOST | Adresse de liaison | 0.0.0.0 |
DROIDGROUND_PORT | Port de liaison | 4242 |
DROIDGROUND_RESTART_APP_DISABLED | Désactiver le redémarrage de l'application | false |
DROIDGROUND_APP_MANAGER_DISABLED | Désactiver le gestionnaire d'applications | false |
DROIDGROUND_BUG_REPORT_DISABLED | Désactiver le rapport de bug | false |
DROIDGROUND_FILE_BROWSER_DISABLED | Désactiver le navigateur de fichiers | false |
DROIDGROUND_FRIDA_DISABLED | Désactiver le support Frida | false |
DROIDGROUND_FRIDA_TYPE | jail ou full | jail |
DROIDGROUND_FRIDA_INJECTION | server ou gadget | server |
DROIDGROUND_LOGCAT_DISABLED | Désactiver logcat | false |
DROIDGROUND_REBOOT_ENABLED | Activer le redémarrage | false |
DROIDGROUND_SHUTDOWN_ENABLED | Activer l'extinction | false |
DROIDGROUND_START_ACTIVITY_DISABLED | Désactiver startActivity | false |
DROIDGROUND_START_RECEIVER_DISABLED | Désactiver la diffusion | false |
DROIDGROUND_START_SERVICE_DISABLED | Désactiver startService | false |
DROIDGROUND_TERMINAL_DISABLED | Désactiver le terminal | false |
DROIDGROUND_RESET_DISABLED | Désactiver la réinitialisation | false |
DROIDGROUND_SCRCPY_CONTROL_ENABLED | Activer l'entrée souris, tactile et clavier via l'écran de l'appareil | false |
DROIDGROUND_SCRCPY_MAX_SIZE | Dimension vidéo maximale en pixels ; 0 conserve la résolution complète de l'appareil | 1280 |
DROIDGROUND_SCRCPY_MAX_FPS | Fréquence d'images vidéo maximale ; 0 la laisse sans limite | 60 |
DROIDGROUND_SCRCPY_VIDEO_BIT_RATE | Débit binaire vidéo en bits par seconde | 4000000 |
DROIDGROUND_EXPLOIT_APP_DURATION | Le temps (en secondes) pendant lequel l'application d'exploit sera active | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | La taille maximale (en Mo) de l'application d'exploit | 50 |
DROIDGROUND_NUM_TEAMS | Le nombre d'équipes jouant simultanément | - |
DROIDGROUND_TEAM_TOKEN_<N> | Le token de la nième équipe. Auto-généré s'il est manquant | - |
DROIDGROUND_IP_STATIC | L'adresse IP statique à afficher. Elle a la priorité sur DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | L'interface réseau pour l'adresse IP affichée | - |
DROIDGROUND_LOGO_LINK | Définir optionnellement le lien de clic du logo (par exemple, votre page principale de CTF) | - |
Définissez DROIDGROUND_SCRCPY_CONTROL_ENABLED=true et redémarrez DroidGround pour rendre l'écran de l'appareil interactif. Cliquez ou tapez sur l'écran pour le focaliser, puis cliquez, faites glisser, balayez, utilisez plusieurs points de contact, faites défiler avec la molette de la souris ou tapez. Clic droit ou appuyez sur Échap pour le retour Android. Tab et Shift+Tab déplacent le focus hors de l'écran. L'entrée est partagée par tous ceux qui consultent l'appareil, y compris en mode équipe. La valeur par défaut reste un écran en lecture seule. La saisie de texte utilise l'injection de touches Android de scrcpy, donc la prise en charge des caractères dépend du mappage du clavier de l'appareil.
Le DROIDGROUND_IP_IFACE cherche d'abord une correspondance exacte et se rabat sur la première interface qui commence par la valeur fournie, car Docker ne permet de spécifier que le préfixe de l'interface réseau dans le conteneur.
La diffusion de l'écran utilise par défaut une dimension maximale de 1280 pixels, jusqu'à 60 fps et 4 Mbps pour réduire le travail d'encodage, de réseau et de navigateur. Cela échange certains détails fins contre la réactivité dans la vue intégrée de l'appareil. Définissez DROIDGROUND_SCRCPY_MAX_SIZE=0 et DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000 pour restaurer les paramètres de qualité en pleine résolution précédents. Pour les connexions ou navigateurs plus lents, essayez une taille maximale de 1024, 30 fps et 2000000 bits par seconde. Redémarrez DroidGround après avoir modifié ces paramètres.
Le navigateur utilise WebCodecs lorsqu'il est disponible et se rabat sinon sur le décodeur logiciel H.264. WebCodecs nécessite un contexte sécurisé : utilisez HTTPS pour les déploiements distants (localhost fonctionne aussi). Le HTTP simple sur une IP ou un nom d'hôte distant utilise le décodage logiciel. Les visionneuses lentes sautent à une nouvelle image clé au lieu d'accumuler un retard vidéo ; rejoindre ou récupérer peut prendre environ un intervalle d'image clé (une seconde). Voir la spécification WebCodecs et la documentation vidéo scrcpy pour les paramètres sous-jacents du navigateur et de la vidéo.
L'utilisation de la variable DROIDGROUND_NUM_TEAMS modifie légèrement le comportement de l'application en interne. Si cette option est définie :
- La fonctionnalité de serveur d'exploit est activée, permettant à chaque équipe de pouvoir utiliser son propre serveur d'exploit (très simple) via son token d'équipe.
- Le token d'équipe sera requis pour installer et exécuter des applications d'exploit. Chaque application installée sera liée à une équipe et les autres équipes ne pourront pas l'exécuter.
Cela permet de partager la même instance DroidGround avec plusieurs équipes dans des challenges où le flag peut être exfiltré via une requête réseau. Cela réduit massivement les coûts de déploiement de DroidGround pour les compétitions CTF.
De plus, si la valeur est définie à -1, cela activera le mode dit Équipes Illimitées. Dans ce mode, un bouton pour générer un nouveau token d'équipe sera disponible dans la page Vue d'ensemble. Toutes les variables DROIDGROUND_TEAM_TOKEN_<N> sont ignorées si ce mode est activé.
🧩 Cas d'usage
Voici quelques façons d'utiliser DroidGround :
- Activité cachée : Trouver et lancer une activité non exposée pour voir le flag (l'application du joueur contient un faux flag).
- RCE : L'application est vulnérable à la RCE et le flag est stocké sur l'appareil.
- Instrumentation Frida : Surcharger une méthode et extraire le flag de la mémoire privée à l'aide d'un script.
⚙️ Utilisation
Quelques fichiers Docker Compose d'exemple sont fournis dans le dossier examples. Ils utilisent des applications du dépôt d'exemples DroidGround qui seront progressivement améliorées pour présenter toutes les fonctionnalités clés. Ils constituent également un bon point de départ pour comprendre comment configurer votre propre CTF.
Au démarrage, DroidGround effectue les opérations suivantes :
- Établir la connexion avec
adb - Exécuter le
setup.shdans le dossier spécifié parDROIDGROUND_INIT_SCRIPTS_FOLDERs'il est présent. Ce script peut être utilisé pour installer l'application cible et faire tout ce qui est nécessaire pour initialiser le CTF (par exemple, placer le flag dans un emplacement connu) - (si Frida est activé) Télécharger le bon
frida-serveren fonction de la version installée et de l'architecture de l'appareil et le démarrer - Exécuter l'application cible (celle spécifiée via
DROIDGROUND_APP_PACKAGE_NAME). Si l'application n'est pas installée, DroidGround se fermera. - Configurer les API REST, les serveurs WebSocket et la diffusion de l'affichage
Voici un exemple 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"
Pour un déploiement en production (dans un vrai CTF), vous voudrez peut-être provisionner un nombre prédéfini d'instances DroidGround à l'avance ou permettre aux utilisateurs de créer des instances (avec une limitation ou peut-être associer chaque équipe/utilisateur à une instance spécifique). Pour cette raison, nous avons également ajouté un simple exemple de spawner.
Alternativement, comme mentionné précédemment, vous pouvez créer un challenge où le flag peut être exfiltré via une requête réseau et tirer parti de la variable d'environnement DROIDGROUND_NUM_TEAMS pour éviter de créer plusieurs instances (ce qui pourrait être coûteux). Le dossier net-multi-step fournit un bon exemple sur la façon de proposer ce type de challenges.
💡 Astuces
Voici quelques suggestions pour configurer votre CTF Android :
- Soyez prudent lors de l'activation du Mode Frida Complet, le joueur aura un contrôle total sur l'appareil (c'est pourquoi nous avons créé le Mode Frida Jail comme détaillé dans Bibliothèque Frida).
- Soyez prudent lors de l'activation du Terminal, le joueur aura un contrôle total sur l'appareil.
- Soyez prudent lors de l'activation de la fonctionnalité Extinction.
- Si vous prévoyez de rendre le flag directement visible dans l'interface utilisateur, vous voudrez peut-être trouver un moyen de créer différentes instances (une pour chaque équipe/joueur)
Lors des tests de la configuration avant de passer en production, il pourrait être utile d'obtenir la surface d'attaque de l'application cible. C'est quelque chose que les joueurs ne devraient pas voir car c'est leur travail de découvrir et d'analyser la surface d'attaque !
Par conséquent, un point de terminaison GET accessible à /attackSurface est fourni et protégé par un token (qui doit être utilisé comme valeur de l'en-tête Authorization) généré aléatoirement lors du démarrage et imprimé dans les journaux (donc accessible uniquement par les administrateurs système).
Si vous souhaitez utiliser vos propres scripts Frida en mode jail, il vous suffit de monter le dossier qui les contient dans le conteneur Docker :
volumes:
- <Frida library folder>:/droidground/library
Un fichier library.json (comme celui dans library) est requis pour indiquer à l'application la liste des scripts disponibles.
🛠 Développement
Le mettre en route ne devrait pas être trop difficile, mais avant de commencer, vous devez avoir les outils suivants installés :
frida(uniquement si vous activez Frida)node(c'est une application Node, vous devez l'avoir !)adb(eh bien, nous comptons sur lui pour communiquer avec l'appareil)- JDK (vous en avez besoin pour compiler l'application compagnon)
Après cela, vous pouvez simplement exécuter ce qui suit :
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
Après cela, il vous suffit de définir les variables env puis d'exécuter npm run dev et vous serez prêt. Bon mode dev !
🤝 Contribution
Les pull requests sont les bienvenues ! Veuillez d'abord ouvrir une issue pour discuter des changements majeurs. Les idées de nouveaux workflows CTF ou types de challenges sont particulièrement appréciées.
📚 Crédits
Développé par Angelo Delicato @SECFORCE.
La section server repose fortement sur l'incroyable travail réalisé par @yume-chan, cette application n'existerait probablement pas sans son travail remarquable.
L'application companion est largement basée sur le serveur aya qui fonctionne de la même manière que le serveur scrcpy. Plus de détails peuvent être trouvés dans le README spécifique.
🪪 Licence
DroidGround est publié sous la LICENCE GPL-3.0







