
droidground v1.0.14
Un parco giochi flessibile per le sfide CTF su Android.
DroidGround
Nelle tradizionali CTF challenge, è comune nascondere le flag in file all'interno di un sistema, richiedendo agli attaccanti di sfruttare vulnerabilità per recuperarle. Tuttavia, nel mondo Android, questo approccio non funziona bene. I file APK sono facilmente scaricabili e reversibili, quindi inserire una flag sul dispositivo la rende solitamente banale da estrarre tramite analisi statica o trucchi sull'emulatore. Questo limita severamente la possibilità di creare challenge realistiche e focalizzate sul runtime.
DroidGround è progettato per risolvere questo problema.
È una piattaforma costruita su misura per ospitare challenge di hacking mobile Android in un ambiente controllato e realistico, dove gli attaccanti sono vincolati quanto basta per richiedere la risoluzione delle challenge nel modo previsto.
È importante notare che i partecipanti possono essere isolati all'interno dell'ambiente dell'app. La modularità dello strumento permette di stabilire se l'utente può o non può avviare una shell, leggere file arbitrari o installare strumenti tramite sideload. Tutto può essere configurato in modo che l'unico modo per recuperare la flag sia comprendere e sfruttare l'app stessa.
📋 Indice
- 🧭 Panoramica
- ✨ Funzionalità
- 📸 Screenshot
- ⚙️ Configurazione
- 🧩 Casi d'uso
- ⚙️ Utilizzo
- 💡 Suggerimenti
- 🛠 Sviluppo
- 🤝 Contribuire
- 📚 Crediti
- 🪪 Licenza
🧭 Panoramica
DroidGround abilita un'ampia varietà di challenge Android che altrimenti sarebbero difficili da implementare nelle configurazioni CTF tradizionali. Ad esempio, in una challenge di remote code execution (RCE), i giocatori potrebbero ricevere un APK per l'analisi locale. Dopo aver scoperto una vulnerabilità, possono sviluppare uno script Frida ed eseguirlo tramite DroidGround sul dispositivo target reale per estrarre la flag dallo storage interno. Altri tipi di challenge possono coinvolgere activity nascoste, broadcast intent personalizzati, sfruttamento di service o analisi dinamica utilizzando strumenti precaricati.
Con lo streaming del dispositivo in tempo reale, il controllo granulare sulle funzionalità, l'integrazione con Frida e script di setup e reset personalizzabili, DroidGround consente agli organizzatori di CTF di costruire challenge Android sicure, flessibili e realistiche che vanno ben oltre ciò che è tipicamente possibile.
✨ Funzionalità
DroidGround fornisce un ricco set di funzionalità controllate dal server.
- Schermo del dispositivo in tempo reale (tramite
scrcpy), con controllo opzionale di mouse, touch e tastiera - Reset dello stato della challenge
- Riavvia App / Avvia Activity / Avvia Service
- Invia Broadcast Intent
- Spegni / Riavvia il dispositivo
- Scarica Bugreport (bugreportz)
- Scripting Frida
- Esegui dalla libreria precaricata (modalità jail)
- Esegui script arbitrari (modalità full)
- File Browser
- Accesso al Terminale
- Gestione APK
- Visualizzatore Logcat
- Exploit Server (se la modalità team è abilitata)
Quasi tutte le funzionalità sono modulari e definite tramite variabili d'ambiente, garantendo un controllo preciso sull'ambito della challenge.
📸 Screenshot
![]() | ![]() |
|---|---|
| Panoramica | Avvia Activity |
![]() | ![]() |
| Modalità Frida Jail | Modalità Frida Full |
![]() | ![]() |
| File Browser | App Manager |
![]() | ![]() |
| Terminale | Log |
⚙️ Configurazione
Il file .env.sample nella directory principale è un buon punto di partenza. Questa è la lista completa di tutte le variabili d'ambiente attualmente supportate:
| Variabile | Descrizione | Default |
|---|---|---|
DROIDGROUND_BASE_PATH | Percorso della webapp (utile per l'hosting su sottopercorsi) | - |
DROIDGROUND_APP_PACKAGE_NAME | Nome del pacchetto dell'app target | - |
DROIDGROUND_ADB_HOST | Host ADB | localhost |
DROIDGROUND_ADB_PORT | Porta ADB | 5037 |
DROIDGROUND_ADB_SERIAL | Seriale opzionale del dispositivo ADB a cui connettersi | - |
DROIDGROUND_DEVICE_TYPE | usb o network | usb |
DROIDGROUND_DEVICE_HOST | IP del dispositivo Android (adb) (solo modalità network) | - |
DROIDGROUND_DEVICE_PORT | porta del dispositivo Android (adb) (solo modalità network) | - |
DROIDGROUND_INIT_SCRIPTS_FOLDER | Cartella contenente setup.sh e reset.sh | /init.d |
DROIDGROUND_HOST | Indirizzo di bind | 0.0.0.0 |
DROIDGROUND_PORT | Porta di bind | 4242 |
DROIDGROUND_RESTART_APP_DISABLED | Disabilita il riavvio dell'app | false |
DROIDGROUND_APP_MANAGER_DISABLED | Disabilita l'app manager | false |
DROIDGROUND_BUG_REPORT_DISABLED | Disabilita il bugreport | false |
DROIDGROUND_FILE_BROWSER_DISABLED | Disabilita il file browser | false |
DROIDGROUND_FRIDA_DISABLED | Disabilita il supporto Frida | false |
DROIDGROUND_FRIDA_TYPE | jail o full | jail |
DROIDGROUND_FRIDA_INJECTION | server o gadget | server |
DROIDGROUND_LOGCAT_DISABLED | Disabilita logcat | false |
DROIDGROUND_REBOOT_ENABLED | Abilita il riavvio | false |
DROIDGROUND_SHUTDOWN_ENABLED | Abilita lo spegnimento | false |
DROIDGROUND_START_ACTIVITY_DISABLED | Disabilita startActivity | false |
DROIDGROUND_START_RECEIVER_DISABLED | Disabilita broadcast | false |
DROIDGROUND_START_SERVICE_DISABLED | Disabilita startService | false |
DROIDGROUND_TERMINAL_DISABLED | Disabilita il terminale | false |
DROIDGROUND_RESET_DISABLED | Disabilita il reset | false |
DROIDGROUND_SCRCPY_CONTROL_ENABLED | Abilita input di mouse, touch e tastiera tramite lo schermo del dispositivo | false |
DROIDGROUND_SCRCPY_MAX_SIZE | Dimensione massima del video in pixel; 0 mantiene la risoluzione completa del dispositivo | 1280 |
DROIDGROUND_SCRCPY_MAX_FPS | Frame rate massimo del video; 0 lo lascia senza limiti | 60 |
DROIDGROUND_SCRCPY_VIDEO_BIT_RATE | Bitrate video in bit al secondo | 4000000 |
DROIDGROUND_EXPLOIT_APP_DURATION | Il tempo (in secondi) durante il quale l'app exploit sarà attiva | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | La dimensione massima (in MB) dell'app exploit | 50 |
DROIDGROUND_NUM_TEAMS | Il numero di team che giocano simultaneamente | - |
DROIDGROUND_TEAM_TOKEN_<N> | Il token per l'n-esimo team. Generato automaticamente se mancante | - |
DROIDGROUND_IP_STATIC | L'indirizzo IP statico da visualizzare. Ha la precedenza su DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | L'interfaccia di rete per l'indirizzo IP visualizzato | - |
DROIDGROUND_LOGO_LINK | Imposta opzionalmente il link click-through del logo (es. la pagina principale della tua CTF) | - |
Imposta DROIDGROUND_SCRCPY_CONTROL_ENABLED=true e riavvia DroidGround per rendere interattivo lo schermo del dispositivo. Clicca o tocca lo schermo per metterlo a fuoco, poi clicca, trascina, scorri, usa più punti di contatto, scorri con la rotellina del mouse o digita. Fai clic destro o premi Escape per il Back di Android. Tab e Shift+Tab spostano il focus fuori dallo schermo. L'input è condiviso da tutti coloro che visualizzano il dispositivo, anche in modalità team. Il default rimane uno schermo di sola visualizzazione. L'input di testo utilizza l'iniezione di tasti Android di scrcpy, quindi il supporto dei caratteri dipende dalla mappatura della tastiera del dispositivo.
La variabile DROIDGROUND_IP_IFACE cerca prima una corrispondenza esatta e ripiega sulla prima interfaccia che inizia con il valore fornito, poiché Docker consente di specificare solo il prefisso dell'interfaccia di rete all'interno del container.
Lo streaming dello schermo utilizza come default una dimensione massima di 1280 pixel, fino a 60 fps e 4 Mbps per ridurre il carico di codifica, rete e browser. Questo sacrifica un po' di dettaglio fine in favore della reattività nella vista del dispositivo incorporata. Imposta DROIDGROUND_SCRCPY_MAX_SIZE=0 e DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000 per ripristinare le precedenti impostazioni di qualità a risoluzione completa. Per connessioni o browser più lenti, prova una dimensione massima di 1024, 30 fps e 2000000 bit al secondo. Riavvia DroidGround dopo aver modificato queste impostazioni.
Il browser utilizza WebCodecs quando disponibile e ripiega altrimenti sul decoder software H.264. WebCodecs richiede un contesto sicuro: usa HTTPS per i deployment remoti (anche localhost funziona). HTTP semplice su un IP o hostname remoto utilizza la decodifica software. I visualizzatori lenti saltano a un keyframe fresco invece di accumulare un backlog video; l'ingresso o il recupero può richiedere circa un intervallo di keyframe (un secondo). Consulta la specifica WebCodecs e la documentazione video di scrcpy per le impostazioni sottostanti di browser e video.
L'utilizzo della variabile DROIDGROUND_NUM_TEAMS cambia leggermente il comportamento dell'applicazione sotto il cofano. Se questa opzione è impostata:
- La funzionalità exploit server è abilitata, consentendo a ciascun team di poter utilizzare il proprio (molto semplice) exploit server tramite il proprio team token.
- Il team token sarà richiesto per installare ed eseguire app exploit. Ogni app installata sarà legata a un team e gli altri team non potranno eseguirla.
Questo permette di condividere la stessa istanza DroidGround con più team in challenge dove la flag può essere esfiltrata tramite una richiesta di rete. Questo riduce massicciamente i costi di deploy di DroidGround per le competizioni CTF.
Inoltre, se il valore è impostato a -1 abiliterà la cosiddetta modalità Unlimited Teams. In questa modalità sarà disponibile un pulsante per generare un nuovo team token nella pagina Overview. Tutte le variabili DROIDGROUND_TEAM_TOKEN_<N> vengono ignorate se questa modalità è abilitata.
🧩 Casi d'uso
Ecco alcuni modi in cui DroidGround può essere utilizzato:
- Activity nascosta: Trova e avvia un'activity non esposta per vedere la flag (l'app del giocatore contiene una flag fittizia).
- RCE: L'app è vulnerabile a RCE e la flag è memorizzata sul dispositivo.
- Strumentazione Frida: Sovraccarica un metodo ed estrai la flag dalla memoria privata usando uno script.
⚙️ Utilizzo
Un paio di file Docker Compose di esempio sono forniti nella cartella examples. Utilizzano app dal repository dei campioni DroidGround che verrà progressivamente arricchito per mostrare tutte le funzionalità chiave. Sono anche un buon punto di partenza per capire come configurare la tua CTF.
All'avvio DroidGround esegue le seguenti operazioni:
- Imposta la connessione con
adb - Esegue il
setup.shnella cartella specificata daDROIDGROUND_INIT_SCRIPTS_FOLDERse presente. Questo script può essere utilizzato per installare l'app target e fare tutto il resto necessario per inizializzare la CTF (es. posizionare la flag in una posizione nota) - (se Frida è abilitato) Scarica il corretto
frida-serverin base alla versione installata e all'architettura del dispositivo e lo avvia - Esegue l'app target (quella specificata tramite
DROIDGROUND_APP_PACKAGE_NAME). Se l'app non è installata DroidGround terminerà. - Configura le REST API, i server WebSocket e lo streaming del display
Ecco un esempio di 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"
Per un deploy in produzione (in una CTF reale) potresti voler predisporre in anticipo un numero predefinito di istanze DroidGround oppure potresti voler consentire agli utenti di generare istanze (con una limitazione o magari associare ogni team/utente a un'istanza specifica). Per questo motivo abbiamo anche aggiunto un semplice esempio di spawner.
In alternativa, come menzionato in precedenza, puoi creare una challenge dove la flag può essere esfiltrata tramite una richiesta di rete e sfruttare la variabile d'ambiente DROIDGROUND_NUM_TEAMS per evitare di generare più istanze (che potrebbe essere costoso). La cartella net-multi-step fornisce un buon esempio su come realizzare questo tipo di challenge.
💡 Suggerimenti
Ecco alcuni suggerimenti per configurare la tua CTF Android:
- Fai attenzione quando abiliti la Frida Full Mode, il giocatore avrà il controllo completo sul dispositivo (è per questo che abbiamo creato la Frida Jail Mode come dettagliato in Frida Library).
- Fai attenzione quando abiliti il Terminale, il giocatore avrà il controllo completo sul dispositivo.
- Fai attenzione quando abiliti la funzionalità di Shutdown.
- Se prevedi di rendere la flag direttamente visibile nella UI potresti voler trovare un modo per generare istanze diverse (una per ogni team/giocatore)
Durante il test della configurazione prima di andare in produzione potrebbe essere utile ottenere la attack surface dell'app target. Questa è qualcosa che i giocatori non dovrebbero vedere perché fa parte del loro lavoro scoprire e analizzare la attack surface!
Pertanto, viene fornito un endpoint GET raggiungibile a /attackSurface e protetto con un token (che deve essere utilizzato come valore dell'header Authorization) generato casualmente durante l'avvio e stampato nei log (quindi accessibile solo dai sysadmin).
Se vuoi usare i tuoi script Frida in modalità jailed, devi semplicemente fare il bind-mount della cartella che li contiene nel container Docker:
volumes:
- <Frida library folder>:/droidground/library
È richiesto un file library.json (come quello in library) per indicare all'applicazione la lista degli script disponibili.
🛠 Sviluppo
Metterlo in funzione non dovrebbe essere troppo difficile, ma prima di iniziare dovresti avere installati i seguenti strumenti:
frida(solo se abiliti Frida)node(è un'app Node, devi averlo!)adb(beh, ci affidiamo ad esso per comunicare con il dispositivo)- JDK (ti serve per compilare l'app companion)
Dopodiché puoi semplicemente eseguire quanto segue:
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
Dopodiché devi solo impostare le variabili env e poi eseguire npm run dev e sarai pronto a partire. Buona modalità dev!
🤝 Contribuire
Le pull request sono benvenute! Apri prima una issue per discutere modifiche importanti. Idee per nuovi workflow CTF o tipi di challenge sono particolarmente apprezzate.
📚 Crediti
Sviluppato da Angelo Delicato @SECFORCE.
La sezione server si basa fortemente sullo straordinario lavoro svolto da @yume-chan, probabilmente questa app non esisterebbe se non fosse stato per il suo straordinario lavoro.
L'app companion è fortemente basata sull'aya server che funziona allo stesso modo dello scrcpy server. Maggiori dettagli possono essere trovati nello specifico README.
🪪 Licenza
DroidGround è rilasciato sotto la GPL-3.0 LICENSE







