
Un terrain de jeu flexible pour les défis CTF Android.
DroidGround
Dans les défis CTF traditionnels, il est courant de cacher des flags dans des fichiers sur un système, ce qui oblige 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 faciles à télécharger et à rétro-concevoir : placer un flag sur l'appareil rend donc généralement son extraction triviale à l'aide d'analyses statiques ou d'astuces d'émulateur. Cela limite fortement la possibilité de créer des défis réalistes, centrés sur l'exécution.
DroidGround a été conçu pour résoudre ce problème.
Il s'agit d'une plateforme sur mesure pour héberger des défis de hacking mobile Android dans un environnement contrôlé et réaliste, où les attaquants sont contraints juste ce qu'il faut pour devoir résoudre les défis de la manière prévue.
Point important : les participants peuvent être confiné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 installer des outils en sideload. 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.
DroidGround permet de créer une grande variété de défis Android difficiles à mettre en œuvre dans les configurations CTF traditionnelles. Par exemple, dans un défi d'exécution de code à distance (RCE), les joueurs peuvent recevoir un APK pour une 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 afin d'extraire le flag du stockage interne. D'autres types de défis peuvent impliquer des activités cachées, des intentions de diffusion (broadcast intents) personnalisées, l'exploitation de services ou l'analyse dynamique à l'aide d'outils préchargés.
Grâce au streaming de l'appareil en temps réel, au contrôle fin des fonctionnalités, à l'intégration de Frida et aux scripts de configuration et de réinitialisation personnalisables, DroidGround permet aux organisateurs de CTF de créer des défis Android sécurisés, flexibles et réalistes, bien au-delà de ce qui est généralement possible.
DroidGround fournit un riche ensemble de fonctionnalités contrôlées par le serveur.
scrcpy)La quasi-totalité des fonctionnalités est modulaire et définie via des variables d'environnement, ce qui garantit un contrôle précis du périmètre du défi.
Le fichier .env.sample à la racine est un bon point de départ. Voici la liste complète de toutes les variables d'environnement actuellement prises en charge :
La variable DROIDGROUND_IP_IFACE recherche d'abord une correspondance exacte, puis 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.
L'utilisation de la variable DROIDGROUND_NUM_TEAMS modifie légèrement le comportement interne de l'application. Si cette option est définie :
Cela permet de partager la même instance DroidGround entre plusieurs équipes dans des défis 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 sur -1, le mode dit Unlimited Teams (équipes illimitées) est activé. Dans ce mode, un bouton permettant de générer un nouveau jeton d'équipe est disponible sur la page Aperçu. Toutes les variables DROIDGROUND_TEAM_TOKEN_<N> sont ignorées lorsque ce mode est activé.
Voici quelques façons d'utiliser DroidGround :
Quelques exemples de fichiers Docker Compose sont fournis dans le dossier examples. Ils utilisent des applications du dépôt d'exemples DroidGround qui sera progressivement enrichi 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 :
adbsetup.sh dans le dossier spécifié par DROIDGROUND_INIT_SCRIPTS_FOLDER s'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 à un emplacement connu)frida-server approprié en fonction de la version installée et de l'architecture de l'appareil, puis le démarrerDROIDGROUND_APP_PACKAGE_NAME). Si l'application n'est pas installée, DroidGround se termine.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 pouvez provisionner un nombre prédéfini d'instances DroidGround à l'avance, ou laisser les utilisateurs créer des instances (avec une limitation, ou en associant chaque équipe/utilisateur à une instance spécifique). C'est pourquoi nous avons également ajouté un simple exemple de générateur (spawner).
Alternativement, comme mentionné précédemment, vous pouvez créer un défi où le flag peut être exfiltré via une requête réseau et utiliser la variable d'environnement DROIDGROUND_NUM_TEAMS pour éviter de créer plusieurs instances (ce qui peut être coûteux). Le dossier net-multi-step fournit un bon exemple de la manière de concevoir ce type de défis.
Voici quelques suggestions pour configurer votre CTF Android :
Lors des tests de configuration avant de passer en production, il peut être utile d'obtenir la surface d'attaque de l'application cible. C'est une information que les joueurs ne devraient pas voir, car découvrir et analyser la surface d'attaque fait partie de leur mission !
C'est pourquoi un endpoint GET accessible à /attackSurface est fourni et protégé par un jeton (à utiliser comme valeur de l'en-tête Authorization), généré aléatoirement au démarrage et affiché dans les journaux (donc accessible uniquement aux administrateurs système).
Si vous souhaitez utiliser vos propres scripts Frida en mode confiné, il vous suffit de monter (bind-mount) le dossier qui les contient dans le conteneur Docker :
volumes:
- <Frida library folder>:/droidground/library
Un fichier library.json (comme celui du dossier library) est requis pour indiquer à l'application la liste des scripts disponibles.
La mise en route ne devrait pas être trop difficile, mais avant de commencer, vous devez avoir installé les outils suivants :
frida (uniquement si vous activez Frida)node (c'est une application Node, il vous le faut !)adb (nous comptons dessus pour communiquer avec l'appareil)Ensuite, il vous suffit d'exécuter les commandes suivantes :
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
Il ne vous reste ensuite qu'à définir les variables d'environnement puis à lancer npm run dev, et vous êtes prêt. Bon mode dev !
Les pull requests sont les bienvenues ! Veuillez d'abord ouvrir une issue pour discuter des changements importants. Les idées de nouveaux workflows CTF ou de nouveaux types de défis sont particulièrement appréciées.
Développé par Angelo Delicato @SECFORCE.
La partie server repose en grande partie sur l'incroyable travail de @yume-chan ; cette application n'existerait probablement pas sans son travail remarquable.
L'application companion est fortement basée sur le serveur aya qui fonctionne de la même manière que le serveur scrcpy. Plus de détails sont disponibles dans le README dédié.
DroidGround est publié sous la licence GPL-3.0.
![]() | ![]() |
|---|
| Aperçu | Démarrer une activité |
![]() | ![]() |
| Mode confiné Frida | Mode complet Frida |
![]() | ![]() |
| Navigateur de fichiers | Gestionnaire d'applications |
![]() | ![]() |
| Terminal | Journaux |
| Variable | Description | Défaut |
|---|
DROIDGROUND_BASE_PATH | Chemin de l'application web (utile pour un 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 ADB facultatif de l'appareil 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 d'écoute | 0.0.0.0 |
DROIDGROUND_PORT | Port d'écoute | 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 bugreport | 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 les diffusions (broadcast) | 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_EXPLOIT_APP_DURATION | La durée (en secondes) pendant laquelle l'application d'exploit est 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 jeton de la nième équipe. Généré automatiquement s'il est absent | - |
DROIDGROUND_IP_STATIC | L'adresse IP statique à afficher. Elle a priorité sur DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | L'interface réseau pour l'adresse IP affichée | - |
DROIDGROUND_LOGO_LINK | Définir facultativement le lien de redirection du logo (par exemple, la page principale de votre CTF) | - |