
droidground v1.0.14
Um playground flexível para desafios de CTF Android.
DroidGround
Em desafios CTF tradicionais, é comum esconder flags em arquivos de um sistema, exigindo que os atacantes explorem vulnerabilidades para recuperá-las. No entanto, no mundo Android, essa abordagem não funciona bem. Arquivos APK são facilmente baixáveis e reversíveis, então colocar uma flag no dispositivo geralmente torna trivial extraí-la usando análise estática ou truques de emulador. Isso limita severamente a capacidade de criar desafios realistas focados em tempo de execução.
DroidGround foi projetado para resolver esse problema.
É uma plataforma construída sob medida para hospedar desafios de hacking mobile Android em um ambiente controlado e realista, onde os atacantes são restringidos apenas o suficiente para exigir que resolvam os desafios da maneira pretendida.
Importante: os participantes podem ser presos dentro do ambiente do app. A modularidade da ferramenta permite definir se o usuário pode ou não abrir um shell, ler arquivos arbitrários ou instalar ferramentas externas. Tudo pode ser configurado para que a única maneira de recuperar a flag seja através da compreensão e exploração do próprio app.
📋 Índice
- 🧭 Visão Geral
- ✨ Recursos
- 📸 Capturas de Tela
- ⚙️ Configuração
- 🧩 Casos de Uso
- ⚙️ Uso
- 💡 Dicas
- 🛠 Desenvolvimento
- 🤝 Contribuindo
- 📚 Créditos
- 🪪 Licença
🧭 Visão Geral
DroidGround possibilita uma ampla variedade de desafios Android que de outra forma são difíceis de implementar em configurações CTF tradicionais. Por exemplo, em um desafio de execução remota de código (RCE), os jogadores podem receber um APK para análise local. Após descobrir uma vulnerabilidade, eles podem desenvolver um script Frida e executá-lo através do DroidGround no dispositivo alvo real para extrair a flag do armazenamento interno. Outros tipos de desafio podem envolver atividades ocultas, intents de broadcast personalizados, exploração de serviços ou análise dinâmica usando ferramentas pré-carregadas.
Com streaming de dispositivo em tempo real, controle refinado sobre recursos, integração com Frida e scripts de configuração e reset personalizáveis, o DroidGround capacita organizadores de CTF a construir desafios Android seguros, flexíveis e realistas que vão muito além do que normalmente é possível.
✨ Recursos
O DroidGround fornece um conjunto rico de recursos controlados pelo servidor.
- Tela do Dispositivo em Tempo Real (via
scrcpy), com controle opcional de mouse, toque e teclado - Resetar Estado do Desafio
- Reiniciar App / Iniciar Activity / Iniciar Service
- Enviar Broadcast Intent
- Desligar / Reiniciar Dispositivo
- Baixar Bugreport (bugreportz)
- Scripting com Frida
- Executar a partir de biblioteca pré-carregada (modo restrito)
- Executar scripts arbitrários (modo completo)
- Navegador de Arquivos
- Acesso ao Terminal
- Gerenciamento de APK
- Visualizador de Logcat
- Servidor de Exploit (se o modo de equipe estiver habilitado)
Quase todos os recursos são modulares e definidos via variáveis de ambiente, garantindo controle preciso sobre o escopo do desafio.
📸 Capturas de Tela
![]() | ![]() |
|---|---|
| Visão Geral | Iniciar Activity |
![]() | ![]() |
| Modo Restrito do Frida | Modo Completo do Frida |
![]() | ![]() |
| Navegador de Arquivos | Gerenciador de Apps |
![]() | ![]() |
| Terminal | Logs |
⚙️ Configuração
O arquivo .env.sample no diretório raiz é um bom ponto de partida. Esta é a lista completa de todas as variáveis de ambiente atualmente suportadas:
| Variável | Descrição | Padrão |
|---|---|---|
DROIDGROUND_BASE_PATH | Caminho da webapp (útil para hospedar em subcaminhos) | - |
DROIDGROUND_APP_PACKAGE_NAME | Nome do pacote do app alvo | - |
DROIDGROUND_ADB_HOST | Host do ADB | localhost |
DROIDGROUND_ADB_PORT | Porta do ADB | 5037 |
DROIDGROUND_ADB_SERIAL | Serial opcional do dispositivo ADB para conectar | - |
DROIDGROUND_DEVICE_TYPE | usb ou network | usb |
DROIDGROUND_DEVICE_HOST | IP do dispositivo Android (adb) (apenas modo network) | - |
DROIDGROUND_DEVICE_PORT | porta do dispositivo Android (adb) (apenas modo network) | - |
DROIDGROUND_INIT_SCRIPTS_FOLDER | Pasta contendo setup.sh e reset.sh | /init.d |
DROIDGROUND_HOST | Endereço de bind | 0.0.0.0 |
DROIDGROUND_PORT | Porta de bind | 4242 |
DROIDGROUND_RESTART_APP_DISABLED | Desabilitar reinício do app | false |
DROIDGROUND_APP_MANAGER_DISABLED | Desabilitar gerenciador de apps | false |
DROIDGROUND_BUG_REPORT_DISABLED | Desabilitar bugreport | false |
DROIDGROUND_FILE_BROWSER_DISABLED | Desabilitar navegador de arquivos | false |
DROIDGROUND_FRIDA_DISABLED | Desabilitar suporte ao Frida | false |
DROIDGROUND_FRIDA_TYPE | jail ou full | jail |
DROIDGROUND_FRIDA_INJECTION | server ou gadget | server |
DROIDGROUND_LOGCAT_DISABLED | Desabilitar logcat | false |
DROIDGROUND_REBOOT_ENABLED | Habilitar reinício | false |
DROIDGROUND_SHUTDOWN_ENABLED | Habilitar desligamento | false |
DROIDGROUND_START_ACTIVITY_DISABLED | Desabilitar startActivity | false |
DROIDGROUND_START_RECEIVER_DISABLED | Desabilitar broadcast | false |
DROIDGROUND_START_SERVICE_DISABLED | Desabilitar startService | false |
DROIDGROUND_TERMINAL_DISABLED | Desabilitar terminal | false |
DROIDGROUND_RESET_DISABLED | Desabilitar reset | false |
DROIDGROUND_SCRCPY_CONTROL_ENABLED | Habilitar entrada de mouse, toque e teclado através da tela do dispositivo | false |
DROIDGROUND_SCRCPY_MAX_SIZE | Dimensão máxima do vídeo em pixels; 0 mantém a resolução completa do dispositivo | 1280 |
DROIDGROUND_SCRCPY_MAX_FPS | Taxa de quadros máxima do vídeo; 0 deixa sem limite | 60 |
DROIDGROUND_SCRCPY_VIDEO_BIT_RATE | Bitrate do vídeo em bits por segundo | 4000000 |
DROIDGROUND_EXPLOIT_APP_DURATION | O tempo (em segundos) que o app de exploit ficará ativo | 10 |
DROIDGROUND_EXPLOIT_APP_MAX_SIZE | O tamanho máximo (em MB) do app de exploit | 50 |
DROIDGROUND_NUM_TEAMS | O número de equipes jogando simultaneamente | - |
DROIDGROUND_TEAM_TOKEN_<N> | O token para a enésima equipe. Gerado automaticamente se ausente | - |
DROIDGROUND_IP_STATIC | O endereço IP estático a exibir. Tem precedência sobre DROIDGROUND_IP_IFACE | - |
DROIDGROUND_IP_IFACE | A interface de rede para o endereço IP exibido | - |
DROIDGROUND_LOGO_LINK | Opcionalmente define o link de clique do logo (ex.: sua página principal do CTF) | - |
Defina DROIDGROUND_SCRCPY_CONTROL_ENABLED=true e reinicie o DroidGround para tornar a tela do dispositivo interativa. Clique ou toque na tela para focá-la, depois clique, arraste, deslize, use múltiplos pontos de toque, role com a roda do mouse ou digite. Clique com o botão direito ou pressione Escape para o Voltar do Android. Tab e Shift+Tab movem o foco para fora da tela. A entrada é compartilhada por todos que visualizam o dispositivo, inclusive no modo de equipe. O padrão permanece uma tela somente visualização. A entrada de texto usa a injeção de teclas Android do scrcpy, então o suporte a caracteres depende do mapeamento de teclado do dispositivo.
O DROIDGROUND_IP_IFACE procura primeiro por uma correspondência exata e recorre à primeira interface que começa com o valor fornecido, já que o Docker só permite especificar o prefixo da interface de rede dentro do container.
O streaming de tela usa por padrão uma dimensão máxima de 1280 pixels, até 60 fps e 4 Mbps para reduzir o trabalho de codificação, rede e navegador. Isso troca algum detalhe fino por responsividade na visualização embutida do dispositivo. Defina DROIDGROUND_SCRCPY_MAX_SIZE=0 e DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000 para restaurar as configurações anteriores de qualidade em resolução total. Para conexões ou navegadores mais lentos, tente um tamanho máximo de 1024, 30 fps e 2000000 bits por segundo. Reinicie o DroidGround após alterar essas configurações.
O navegador usa WebCodecs quando disponível e recorre ao decodificador H.264 por software caso contrário. O WebCodecs requer um contexto seguro: use HTTPS para implantações remotas (localhost também funciona). HTTP simples em um IP ou hostname remoto usa decodificação por software. Visualizadores lentos pulam para um keyframe novo em vez de acumular um backlog de vídeo; entrar ou recuperar pode levar cerca de um intervalo de keyframe (um segundo). Consulte a especificação WebCodecs e a documentação de vídeo do scrcpy para as configurações subjacentes de navegador e vídeo.
O uso da variável DROIDGROUND_NUM_TEAMS altera ligeiramente o comportamento da aplicação nos bastidores. Se esta opção estiver definida:
- O recurso de servidor de exploit é habilitado, permitindo que cada equipe possa usar seu próprio servidor de exploit (muito simples) via seu team token.
- O team token será obrigatório para instalar e executar apps de exploit. Cada app instalado ficará vinculado a uma equipe e outras equipes não poderão executá-lo.
Isso permite compartilhar a mesma instância do DroidGround com múltiplas equipes em desafios onde a flag pode ser exfiltrada via requisição de rede. Isso reduz massivamente os custos de implantação do DroidGround para competições CTF.
Além disso, se o valor for definido como -1, ele habilitará o chamado modo Unlimited Teams. Neste modo, um botão para gerar um novo team token estará disponível na página Overview. Todas as variáveis DROIDGROUND_TEAM_TOKEN_<N> são ignoradas se este modo estiver habilitado.
🧩 Casos de Uso
Aqui estão algumas formas pelas quais o DroidGround pode ser usado:
- Activity Oculta: Encontrar e iniciar uma activity não exposta para ver a flag (o app do jogador contém uma flag fictícia).
- RCE: O app é vulnerável a RCE e a flag está armazenada no dispositivo.
- Instrumentação com Frida: Sobrecarregar um método e extrair a flag da memória privada usando um script.
⚙️ Uso
Alguns arquivos de exemplo de Docker Compose são fornecidos na pasta examples. Eles usam apps do repositório de amostras do DroidGround que serão progressivamente aprimorados para demonstrar todos os recursos principais. Eles também são um bom ponto de partida para entender como configurar seu próprio CTF.
Na inicialização, o DroidGround faz o seguinte:
- Configura a conexão com o
adb - Executa o
setup.shna pasta especificada porDROIDGROUND_INIT_SCRIPTS_FOLDER, se presente. Este script pode ser usado para instalar o app alvo e fazer tudo o mais que for necessário para inicializar o CTF (ex.: colocar a flag em um local conhecido) - (se o Frida estiver habilitado) Baixa o
frida-servercorreto com base na versão instalada e na arquitetura do dispositivo e o inicia - Executa o app alvo (aquele especificado através de
DROIDGROUND_APP_PACKAGE_NAME). Se o app não estiver instalado, o DroidGround será encerrado. - Configura as REST APIs, os servidores WebSocket e o streaming de exibição
Aqui está um exemplo 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"
Para uma implantação em produção (em um CTF real), você pode querer provisionar um número predefinido de instâncias do DroidGround antecipadamente ou pode querer permitir que os usuários criem instâncias (com uma limitação ou talvez associar cada equipe/usuário a uma instância específica). Por esse motivo, também adicionamos um simples exemplo de spawner.
Alternativamente, como mencionado anteriormente, você pode criar um desafio onde a flag pode ser exfiltrada via requisição de rede e aproveitar a variável de ambiente DROIDGROUND_NUM_TEAMS para evitar criar múltiplas instâncias (o que poderia ser caro). A pasta net-multi-step fornece um bom exemplo de como entregar esse tipo de desafio.
💡 Dicas
Aqui estão algumas sugestões para configurar seu CTF Android:
- Tenha cuidado ao habilitar o Frida Full Mode, o jogador terá controle completo sobre o dispositivo (é por isso que criamos o Frida Jail Mode conforme detalhado em Frida Library).
- Tenha cuidado ao habilitar o Terminal, o jogador terá controle completo sobre o dispositivo.
- Tenha cuidado ao habilitar o recurso de Shutdown.
- Se você planeja tornar a flag diretamente visível na UI, talvez queira encontrar uma maneira de criar instâncias diferentes (uma para cada equipe/jogador)
Ao testar a configuração antes de ir para produção, pode ser útil obter a superfície de ataque do app alvo. Isso é algo que os jogadores não deveriam ver, porque faz parte do trabalho deles descobrir e analisar a superfície de ataque!
Portanto, um endpoint GET acessível em /attackSurface é fornecido e protegido com um token (que precisa ser usado como valor do cabeçalho Authorization) que é gerado aleatoriamente durante a inicialização e impresso nos logs (portanto, acessível apenas por sysadmins).
Se você quiser usar seus próprios scripts Frida no modo restrito, basta fazer bind-mount da pasta que os contém no container Docker:
volumes:
- <Frida library folder>:/droidground/library
Um arquivo library.json (como o em library) é necessário para instruir a aplicação sobre a lista de scripts disponíveis.
🛠 Desenvolvimento
Colocá-lo em funcionamento não deve ser muito difícil, mas antes de começar você deve ter as seguintes ferramentas instaladas:
frida(apenas se você habilitar o Frida)node(é um app Node, você precisa tê-lo!)adb(bem, dependemos dele para conversar com o dispositivo)- JDK (você precisa dele para compilar o app companion)
Depois disso, você pode simplesmente executar o seguinte:
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
Depois disso, você só precisa definir as variáveis de env e então executar npm run dev e estará pronto para começar. Bom modo dev!
🤝 Contribuindo
Pull requests são bem-vindos! Por favor, abra uma issue primeiro para discutir mudanças importantes. Ideias para novos fluxos de trabalho de CTF ou tipos de desafio são especialmente apreciadas.
📚 Créditos
Desenvolvido por Angelo Delicato @SECFORCE.
A seção server depende fortemente do incrível trabalho feito por @yume-chan, provavelmente este app não existiria se não fosse pelo seu incrível trabalho.
O app companion é fortemente baseado no aya server que funciona da mesma forma que o scrcpy server. Mais detalhes podem ser encontrados no README específico.
🪪 Licença
DroidGround é distribuído sob a GPL-3.0 LICENSE







