
Un terrain de jeu flexible pour les défis CTF Android.
<h1 align="center">
<br>
<img src="https://assets.kitploit.com/production/public/readmes/7301/75c22abcf52c94c756ce37d77db74df73c48b6846c3aede4c8971c38e2180f65.png" alt= "droidground" width="200px">
</h1>
<p align="center">
<b>DroidGround</b>
<p>
<p align="center">
<a href="https://github.com/SECFORCE/droidground/blob/main/README.md"><img src="https://img.shields.io/badge/Documentation-complete-green.svg?style=flat"></a>
<a href="https://github.com/SECFORCE/droidground/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-GPL3-blue.svg"></a>
<a href="https://blackhat.com/eu-25/arsenal/schedule/index.html#droidground-a-flexible-playground-for-android-ctf-challenges-47803"><img src="https://raw.githubusercontent.com/secforce/droidground/HEAD/docs/blackhat-2025.svg"></a>
<br />
<a href="https://droidground.com" target="_blank">Site web</a> |
<a href="https://droidground.com/demo" target="_blank">Démo</a>
</p>
Dans les **CTF challenges** traditionnels, il est courant de cacher des 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 une analyse statique ou des 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.
De manière importante, 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é de sorte 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
- [🧭 Aperçu](#-aperçu)
- [✨ Fonctionnalités](#-fonctionnalités)
- [📸 Captures d'écran](#-captures-décran)
- [⚙️ Configuration](#️-configuration)
- [🧩 Cas d'usage](#-cas-dusage)
- [⚙️ Utilisation](#️-utilisation)
- [💡 Astuces](#-astuces)
- [🛠 Développement](#-développement)
- [🤝 Contribution](#-contribution)
- [📚 Crédits](#-crédits)
- [🪪 Licence](#-licence)
## 🧭 Aperçu
_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 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 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 une analyse dynamique à l'aide d'outils préchargés.
Avec la diffusion en temps réel de l'appareil, un contrôle précis 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 ensemble riche 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
|  |  |
| ------------------------------------------------------ | ----------------------------------------------------- |
| Aperçu | 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 ADB optionnel 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 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 pour 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 touchez l'écran pour le mettre au focus, puis cliquez, faites glisser, balayez, utilisez plusieurs points de contact, faites défiler avec la molette de la souris ou tapez. Cliquez avec le bouton droit ou appuyez sur Échap pour le retour Android. Tab et Maj+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. Par défaut, l'écran reste 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.
`DROIDGROUND_IP_IFACE` recherche 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 de 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 H.264 logiciel. 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. Si aucune image clé n'arrive dans les 1,5 seconde, DroidGround demande un rafraîchissement vidéo ; cela prend en charge des encodeurs tels que `OMX.google.h264.encoder` de ReDroid, dont les I-frames périodiques ne sont pas nécessairement des images IDR décodables indépendamment. Les demandes de rafraîchissement sont partagées entre les visionneuses et peuvent brièvement rafraîchir l'écran pour tout le monde. Le serveur conserve un canal de contrôle scrcpy interne pour les rafraîchissements vidéo ; l'entrée souris, tactile, clavier et le réveil automatique de l'écran restent conditionnés par `DROIDGROUND_SCRCPY_CONTROL_ENABLED`. Consultez la [spécification WebCodecs](https://www.w3.org/TR/webcodecs/#videodecoder-interface) et la [documentation vidéo scrcpy](https://github.com/Genymobile/scrcpy/blob/master/doc/video.md) 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 :
1. 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_**.
2. 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 **Unlimited Teams**. Dans ce mode, un bouton pour générer un nouveau **_token d'équipe_** sera disponible dans la page _Aperçu_. 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 :
1. **Activité cachée** : Trouver et lancer une activité non exposée pour voir le flag (l'application du joueur contient un faux flag).
2. **RCE** : L'application est vulnérable à une RCE et le flag est stocké sur l'appareil.
3. **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](https://github.com/secforce/droidground/blob/main/examples/apps). Ils utilisent des applications du [dépôt d'exemples DroidGround](https://github.com/SECFORCE/droidground-samples) qui seront progressivement enrichies 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 :
1. Établir la connexion avec `adb`
2. Exécuter le `setup.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 dans un emplacement connu)
3. (si _Frida_ est activé) Télécharger le bon `frida-server` en fonction de la version installée et de l'architecture de l'appareil et le démarrer
4. 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.
5. Configurer les _API REST_, les serveurs _WebSocket_ et la diffusion de l'affichage
Voici un exemple de script `setup.sh` :
```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 à l'avance un nombre prédéfini d'instances DroidGround ou permettre aux utilisateurs de lancer 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](https://github.com/secforce/droidground/blob/main/examples/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 lancer plusieurs instances (ce qui pourrait être coûteux). Le dossier [net-multi-step](https://github.com/secforce/droidground/blob/main/examples/apps/net-multi-step) fournit un bon exemple de la façon de proposer ce type de challenges.
## 💡 Astuces
Voici quelques suggestions pour configurer votre CTF Android :
- Soyez prudent lorsque vous activez le **Frida Full Mode**, le joueur aura un contrôle complet sur l'appareil (c'est pourquoi nous avons créé le **Frida Jail Mode** comme détaillé dans [Frida Library](https://github.com/secforce/droidground/blob/main/library)).
- Soyez prudent lorsque vous activez le **Terminal**, le joueur aura un contrôle complet sur l'appareil.
- Soyez prudent lorsque vous activez la fonctionnalité **Shutdown**.
- Si vous prévoyez de rendre le flag directement visible dans l'interface utilisateur, vous voudrez peut-être trouver un moyen de lancer 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 il fait partie de 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 :
```yaml
volumes:
- <Frida library folder>:/droidground/library
```
Un fichier `library.json` (comme celui dans [library](https://github.com/secforce/droidground/blob/main/library/library.json)) 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 :
```sh
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](https://github.com/thelicato) [@SECFORCE](https://www.secforce.com).
La section _server_ repose fortement sur l'incroyable travail réalisé par [@yume-chan](https://github.com/yume-chan/ya-webadb), cette application n'existerait probablement pas sans son travail remarquable.
L'application _companion_ est largement basée sur le [aya server](https://github.com/liriliri/aya/tree/master/server) qui fonctionne de la même manière que le [scrcpy server](https://github.com/Genymobile/scrcpy). Plus de détails peuvent être trouvés dans le [README](https://github.com/secforce/droidground/blob/main/companion/README.md) spécifique.
## 🪪 Licence
_DroidGround_ est publié sous la [LICENCE GPL-3.0](https://github.com/SECFORCE/droidground/blob/main/LICENSE)