
Eine flexible Spielwiese für Android-CTF-Challenges.
DroidGround
In traditionellen CTF-Challenges ist es üblich, Flags in Dateien auf einem System zu verstecken, sodass Angreifer Schwachstellen ausnutzen müssen, um sie zu erhalten. In der Android-Welt funktioniert dieser Ansatz jedoch nicht gut. APK-Dateien sind leicht herunterladbar und reversibel, daher ist es normalerweise trivial, eine Flag auf dem Gerät zu platzieren und sie mithilfe statischer Analyse oder Emulator-Tricks zu extrahieren. Das schränkt die Möglichkeit, realistische, auf die Laufzeit fokussierte Challenges zu erstellen, erheblich ein.
DroidGround wurde entwickelt, um dieses Problem zu lösen.
Es ist eine maßgeschneiderte Plattform zum Hosten von Android-Mobile-Hacking-Challenges in einer kontrollierten und realistischen Umgebung, in der Angreifer gerade genug eingeschränkt sind, um die Challenges auf die beabsichtigte Weise lösen zu müssen.
Wichtig ist, dass die Teilnehmer in die App-Umgebung gesperrt sein können. Die Modularität des Tools erlaubt es festzulegen, ob der Benutzer eine Shell starten, beliebige Dateien lesen oder Tools sideloaden kann. Alles kann so eingerichtet werden, dass der einzige Weg, die Flag zu erhalten, darin besteht, die App selbst zu verstehen und auszunutzen.
DroidGround ermöglicht eine große Vielfalt an Android-Challenges, die in traditionellen CTF-Setups sonst schwer umzusetzen sind. Beispielsweise könnten die Spieler bei einer Remote-Code-Execution-Challenge (RCE) eine APK zur lokalen Analyse erhalten. Nach der Entdeckung einer Schwachstelle können sie ein Frida-Skript entwickeln und es über DroidGround auf dem echten Zielgerät ausführen, um die Flag aus dem internen Speicher zu extrahieren. Andere Challenge-Typen können versteckte Activities, benutzerdefinierte Broadcast-Intents, Service-Exploitation oder dynamische Analyse mit vorinstallierten Tools umfassen.
Mit Echtzeit-Geräte-Streaming, feingranularer Kontrolle über Funktionen, Frida-Integration und anpassbaren Setup- und Reset-Skripten befähigt DroidGround CTF-Organisatoren, sichere, flexible und realistische Android-Challenges zu bauen, die weit über das normalerweise Mögliche hinausgehen.
DroidGround bietet eine umfangreiche Palette an servergesteuerten Funktionen.
scrcpy)Fast alle Funktionen sind modular und werden über Umgebungsvariablen definiert, sodass eine präzise Kontrolle über den Challenge-Umfang gewährleistet ist.
Die Datei .env.sample im Stammverzeichnis ist ein guter Ausgangspunkt. Dies ist die vollständige Liste aller derzeit unterstützten Umgebungsvariablen:
DROIDGROUND_IP_IFACE sucht zuerst nach einer exakten Übereinstimmung und fällt auf die erste Schnittstelle zurück, die mit dem angegebenen Wert beginnt, da Docker innerhalb des Containers nur die Angabe des Netzwerkschnittstellen-Präfixes erlaubt.
Die Verwendung der Variable DROIDGROUND_NUM_TEAMS ändert das Verhalten der Anwendung im Hintergrund leicht. Wenn diese Option gesetzt ist:
Dadurch kann dieselbe DroidGround-Instanz von mehreren Teams bei Challenges genutzt werden, bei denen die Flag über eine Netzwerkanfrage exfiltriert werden kann. Das reduziert die Bereitstellungskosten von DroidGround für CTF-Wettbewerbe massiv.
Darüber hinaus wird bei einem Wert von -1 der sogenannte Unlimited Teams-Modus aktiviert. In diesem Modus ist auf der Seite Übersicht eine Schaltfläche zum Generieren eines neuen Team-Tokens verfügbar. Alle DROIDGROUND_TEAM_TOKEN_<N>-Variablen werden ignoriert, wenn dieser Modus aktiviert ist.
Hier sind einige Möglichkeiten, wie DroidGround verwendet werden kann:
Einige Beispiel-Docker Compose-Dateien sind im Ordner examples enthalten. Sie verwenden Apps aus dem DroidGround-Beispiel-Repository, das nach und nach erweitert wird, um alle wichtigen Funktionen zu demonstrieren. Sie sind auch ein guter Ausgangspunkt, um zu verstehen, wie man ein eigenes CTF einrichtet.
Beim Start führt DroidGround Folgendes aus:
adb einrichtensetup.sh in dem von DROIDGROUND_INIT_SCRIPTS_FOLDER angegebenen Ordner ausführen, falls vorhanden. Dieses Skript kann verwendet werden, um die Ziel-App zu installieren und alles andere zu tun, was zur Initialisierung des CTFs benötigt wird (z. B. die Flag an einem bekannten Ort zu platzieren).frida-server basierend auf der installierten Version und der Architektur des Geräts herunterladen und startenDROIDGROUND_APP_PACKAGE_NAME angegeben wurde). Wenn die App nicht installiert ist, beendet sich DroidGround.Hier ist ein Beispiel für ein setup.sh-Skript:
#!/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"
Für eine Produktionsbereitstellung (in einem echten CTF) möchtest du möglicherweise im Voraus eine festgelegte Anzahl von DroidGround-Instanzen bereitstellen oder den Benutzern erlauben, Instanzen zu erzeugen (mit einer Begrenzung oder vielleicht der Zuordnung jedes Teams/Benutzers zu einer bestimmten Instanz). Aus diesem Grund haben wir auch ein einfaches Spawner-Beispiel hinzugefügt.
Alternativ kannst du, wie bereits erwähnt, eine Challenge erstellen, bei der die Flag über eine Netzwerkanfrage exfiltriert werden kann, und die Umgebungsvariable DROIDGROUND_NUM_TEAMS nutzen, um das Erzeugen mehrerer Instanzen zu vermeiden (was teuer sein kann). Der Ordner net-multi-step bietet ein gutes Beispiel, wie solche Challenges umgesetzt werden können.
Hier sind einige Vorschläge für die Einrichtung deines Android-CTFs:
Beim Testen des Setups vor der Produktion kann es nützlich sein, die Angriffsfläche der Ziel-App zu ermitteln. Das ist etwas, das die Spieler nicht sehen sollten, denn es ist Teil ihrer Aufgabe, die Angriffsfläche zu entdecken und zu analysieren!
Daher wird ein GET-Endpunkt unter /attackSurface bereitgestellt und mit einem Token geschützt (das als Wert des Authorization-Headers verwendet werden muss), das beim Start zufällig generiert und in den Logs ausgegeben wird (also nur für Systemadministratoren zugänglich ist).
Wenn du deine eigenen Frida-Skripte im Jail-Modus verwenden möchtest, musst du nur den Ordner, der sie enthält, in den Docker-Container bind-mounten:
volumes:
- <Frida library folder>:/droidground/library
Eine Datei library.json (wie die in der library) ist erforderlich, um der Anwendung die Liste der verfügbaren Skripte mitzuteilen.
Es sollte nicht allzu schwierig sein, es zum Laufen zu bringen, aber bevor du beginnst, solltest du die folgenden Werkzeuge installiert haben:
frida (nur wenn du Frida aktivierst)node (es ist eine Node-App, du brauchst sie!)adb (nun, wir verlassen uns darauf, um mit dem Gerät zu kommunizieren)Danach kannst du einfach Folgendes ausführen:
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
Danach musst du nur noch die env-Variablen setzen und dann npm run dev ausführen – dann kannst du loslegen. Viel Spaß im Dev-Modus!
Pull-Requests sind willkommen! Bitte eröffne zuerst ein Issue, um größere Änderungen zu besprechen. Ideen für neue CTF-Workflows oder Challenge-Typen sind besonders willkommen.
Entwickelt von Angelo Delicato @SECFORCE.
Der Server-Bereich stützt sich stark auf die großartige Arbeit von @yume-chan; wahrscheinlich würde diese App ohne seine großartige Arbeit nicht existieren.
Die Companion-App basiert stark auf dem aya server, der auf die gleiche Weise funktioniert wie der scrcpy server. Weitere Details findest du in der spezifischen README.
DroidGround wird unter der GPL-3.0-Lizenz veröffentlicht.
![]() | ![]() |
|---|
| Übersicht | Aktivität starten |
![]() | ![]() |
| Frida-Jail-Modus | Frida-Vollmodus |
![]() | ![]() |
| Dateibrowser | App-Manager |
![]() | ![]() |
| Terminal | Logs |
| Variable | Description | Default |
|---|
DROIDGROUND_BASE_PATH | Pfad der Webapp (nützlich für das Hosten auf Unterpfaden) | - |
DROIDGROUND_APP_PACKAGE_NAME | Paketname der Ziel-App | - |
DROIDGROUND_ADB_HOST | ADB-Host | localhost |
DROIDGROUND_ADB_PORT | ADB-Port | 5037 |
DROIDGROUND_ADB_SERIAL | Optionale ADB-Geräteseriennummer, mit der verbunden werden soll | - |
DROIDGROUND_DEVICE_TYPE | usb oder network | usb |
DROIDGROUND_DEVICE_HOST | IP des Android-Geräts (adb) (nur Netzwerkmodus) | - |
DROIDGROUND_DEVICE_PORT | Port des Android-Geräts (adb) (nur Netzwerkmodus) | - |
DROIDGROUND_INIT_SCRIPTS_FOLDER | Ordner, der setup.sh und reset.sh enthält | /init.d |
DROIDGROUND_HOST | Bind-Adresse | 0.0.0.0 |
DROIDGROUND_PORT | Bind-Port | 4242 |
DROIDGROUND_RESTART_APP_DISABLED | App-Neustart deaktivieren | false |
DROIDGROUND_APP_MANAGER_DISABLED | App-Manager deaktivieren | false |
DROIDGROUND_BUG_REPORT_DISABLED | Bugreport deaktivieren | false |
DROIDGROUND_FILE_BROWSER_DISABLED | Dateibrowser deaktivieren | false |
DROIDGROUND_FRIDA_DISABLED | Frida-Unterstützung deaktivieren | false |
DROIDGROUND_FRIDA_TYPE | jail oder full | jail |
DROIDGROUND_FRIDA_INJECTION | server oder gadget | server |
DROIDGROUND_LOGCAT_DISABLED | Logcat deaktivieren | false |
DROIDGROUND_REBOOT_ENABLED | Neustart aktivieren | false |
DROIDGROUND_SHUTDOWN_ENABLED | Herunterfahren aktivieren | false |
DROIDGROUND_START_ACTIVITY_DISABLED | startActivity deaktivieren | false |
DROIDGROUND_START_RECEIVER_DISABLED | Broadcast deaktivieren | false |
DROIDGROUND_START_SERVICE_DISABLED | startService deaktivieren | false |
DROIDGROUND_TERMINAL_DISABLED | Terminal deaktivieren | false |
DROIDGROUND_RESET_DISABLED | Reset deaktivieren | false |
DROIDGROUND_EXPLOIT_APP_DURATION | Die Zeit (in Sekunden), in der die Exploit-App aktiv ist | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | Die maximale Größe (in MB) der Exploit-App | 50 |
DROIDGROUND_NUM_TEAMS | Die Anzahl der gleichzeitig spielenden Teams | - |
DROIDGROUND_TEAM_TOKEN_<N> | Das Token für das n-te Team. Wird automatisch generiert, falls es fehlt | - |
DROIDGROUND_IP_STATIC | Die statische IP-Adresse zur Anzeige. Sie hat Vorrang vor DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | Die Netzwerkschnittstelle für die angezeigte IP-Adresse | - |
DROIDGROUND_LOGO_LINK | Optional den Klick-Ziel-Link des Logos festlegen (z. B. deine CTF-Hauptseite) | - |