
Android CTFチャレンジのための柔軟なプレイグラウンド。
<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">Website</a> |
<a href="https://droidground.com/demo" target="_blank">Demo</a>
</p>
従来の **CTF チャレンジ** では、システム上のファイルにフラグを隠し、攻撃者が脆弱性を悪用してそれを取得する必要があるようにするのが一般的です。しかし、Android の世界ではこのアプローチはうまく機能しません。APK ファイルは簡単にダウンロードしてリバースエンジニアリングできるため、**デバイス上にフラグを置くと、静的解析やエミュレータのトリックを使って抽出するのは通常容易** になります。これは、現実的でランタイムに焦点を当てたチャレンジを作成する能力を著しく制限します。
_DroidGround_ はこの問題を解決するために設計されました。
これは、Android モバイルハッキングチャレンジを **制御された** かつ **現実的な** 環境でホストするためにカスタムビルドされたプラットフォームであり、**攻撃者は意図された方法でチャレンジを解決することを要求される程度にちょうどよく制約** されます。
重要な点として、参加者は **アプリ環境内に閉じ込められる** 可能性があります。このツールのモジュール性により、ユーザーがシェルを起動できるか、任意のファイルを読み取れるか、ツールをサイドロードできるかを設定できます。フラグを取得する唯一の方法がアプリ自体を理解して悪用することになるように、すべてをセットアップできます。
## 📋 目次
- [🧭 概要](#-概要)
- [✨ 機能](#-機能)
- [📸 スクリーンショット](#-スクリーンショット)
- [⚙️ 設定](#️-設定)
- [🧩 ユースケース](#-ユースケース)
- [⚙️ 使用方法](#️-使用方法)
- [💡 ヒント](#-ヒント)
- [🛠 開発](#-開発)
- [🤝 コントリビューション](#-コントリビューション)
- [📚 クレジット](#-クレジット)
- [🪪 ライセンス](#-ライセンス)
## 🧭 概要
_DroidGround_ は、従来の CTF セットアップでは実装が難しい多種多様な _Android_ チャレンジを可能にします。たとえば、リモートコード実行 (RCE) チャレンジでは、プレイヤーはローカル解析用の APK を受け取るかもしれません。脆弱性を発見した後、Frida スクリプトを作成し、DroidGround を通じて実際のターゲットデバイス上で実行して内部ストレージからフラグを抽出できます。他のチャレンジタイプには、隠されたアクティビティ、カスタムブロードキャストインテント、サービスの悪用、またはプリロードされたツールを使用した動的解析が含まれる場合があります。
リアルタイムのデバイスストリーミング、機能に対するきめ細かな制御、Frida 統合、カスタマイズ可能なセットアップおよびリセットスクリプトにより、DroidGround は CTF 主催者が通常可能な範囲をはるかに超えた、安全で柔軟かつ現実的な Android チャレンジを構築できるようにします。
## ✨ 機能
DroidGround は、サーバー制御の豊富な機能セットを提供します。
- **リアルタイムデバイス画面** (`scrcpy` 経由)、オプションでマウス、タッチ、キーボード操作が可能
- **チャレンジ状態のリセット**
- **アプリの再起動 / アクティビティの開始 / サービスの開始**
- **ブロードキャストインテントの送信**
- **デバイスのシャットダウン / 再起動**
- **バグレポートのダウンロード (bugreportz)**
- **Frida スクリプティング**
- プリロードされたライブラリから実行 (ジェイルモード)
- 任意のスクリプトを実行 (フルモード)
- **ファイルブラウザ**
- **ターミナルアクセス**
- **APK 管理**
- **Logcat ビューア**
- **エクスプロイトサーバー** (チームモードが有効な場合)
ほぼすべての機能は **モジュール式** で、環境変数を介して定義されるため、チャレンジの範囲を正確に制御できます。
## 📸 スクリーンショット
|  |  |
| ------------------------------------------------------ | ----------------------------------------------------- |
| 概要 | アクティビティの開始 |
|  |  |
| Frida ジェイルモード | Frida フルモード |
|  |  |
| ファイルブラウザ | アプリマネージャー |
|  |  |
| ターミナル | ログ |
## ⚙️ 設定
ルートディレクトリにある `.env.sample` ファイルは良い出発点です。以下は現在サポートされているすべての環境変数の完全なリストです:
| 変数 | 説明 | デフォルト |
| ------------------------------------- | --------------------------------------------------------------------------------- | ----------- |
| `DROIDGROUND_BASE_PATH` | Web アプリのパス (サブパスでのホストに便利) | - |
| `DROIDGROUND_APP_PACKAGE_NAME` | ターゲットアプリのパッケージ名 | - |
| `DROIDGROUND_ADB_HOST` | ADB ホスト | `localhost` |
| `DROIDGROUND_ADB_PORT` | ADB ポート | `5037` |
| `DROIDGROUND_ADB_SERIAL` | 接続するオプションの ADB デバイスシリアル | - |
| `DROIDGROUND_DEVICE_TYPE` | `usb` または `network` | `usb` |
| `DROIDGROUND_DEVICE_HOST` | Android デバイスの IP (`adb`) (ネットワークモードのみ) | - |
| `DROIDGROUND_DEVICE_PORT` | Android デバイスのポート (`adb`) (ネットワークモードのみ) | - |
| `DROIDGROUND_INIT_SCRIPTS_FOLDER` | `setup.sh` と `reset.sh` を含むフォルダー | `/init.d` |
| `DROIDGROUND_HOST` | バインドアドレス | `0.0.0.0` |
| `DROIDGROUND_PORT` | バインドポート | `4242` |
| `DROIDGROUND_RESTART_APP_DISABLED` | アプリの再起動を無効化 | `false` |
| `DROIDGROUND_APP_MANAGER_DISABLED` | アプリマネージャーを無効化 | `false` |
| `DROIDGROUND_BUG_REPORT_DISABLED` | バグレポートを無効化 | `false` |
| `DROIDGROUND_FILE_BROWSER_DISABLED` | ファイルブラウザを無効化 | `false` |
| `DROIDGROUND_FRIDA_DISABLED` | Frida サポートを無効化 | `false` |
| `DROIDGROUND_FRIDA_TYPE` | `jail` または `full` | `jail` |
| `DROIDGROUND_FRIDA_INJECTION` | `server` または `gadget` | `server` |
| `DROIDGROUND_LOGCAT_DISABLED` | logcat を無効化 | `false` |
| `DROIDGROUND_REBOOT_ENABLED` | 再起動を有効化 | `false` |
| `DROIDGROUND_SHUTDOWN_ENABLED` | シャットダウンを有効化 | `false` |
| `DROIDGROUND_START_ACTIVITY_DISABLED` | startActivity を無効化 | `false` |
| `DROIDGROUND_START_RECEIVER_DISABLED` | ブロードキャストを無効化 | `false` |
| `DROIDGROUND_START_SERVICE_DISABLED` | startService を無効化 | `false` |
| `DROIDGROUND_TERMINAL_DISABLED` | ターミナルを無効化 | `false` |
| `DROIDGROUND_RESET_DISABLED` | リセットを無効化 | `false` |
| `DROIDGROUND_SCRCPY_CONTROL_ENABLED` | デバイス画面を通じたマウス、タッチ、キーボード入力を有効化 | `false` |
| `DROIDGROUND_SCRCPY_MAX_SIZE` | 最大ビデオ解像度 (ピクセル単位)。`0` はデバイスのフル解像度を維持 | `1280` |
| `DROIDGROUND_SCRCPY_MAX_FPS` | 最大ビデオフレームレート。`0` は無制限 | `60` |
| `DROIDGROUND_SCRCPY_VIDEO_BIT_RATE` | ビデオビットレート (ビット毎秒) | `4000000` |
| `DROIDGROUND_EXPLOIT_APP_DURATION` | エクスプロイトアプリがアクティブになる時間 (秒) | `10` |
| `DROIDGROUND_EXPLOIT_APP_MAX_SIZE` | エクスプロイトアプリの最大サイズ (MB) | `50` |
| `DROIDGROUND_NUM_TEAMS` | 同時にプレイするチーム数 | - |
| `DROIDGROUND_TEAM_TOKEN_<N>` | n 番目のチームのトークン。存在しない場合は自動生成 | - |
| `DROIDGROUND_IP_STATIC` | 表示する静的 IP アドレス。`DROIDGROUND_IP_IFACE` より優先される | - |
| `DROIDGROUND_IP_IFACE` | 表示する IP アドレスのネットワークインターフェース | - |
| `DROIDGROUND_LOGO_LINK` | オプションでロゴのクリックスルーリンクを設定 (例: CTF のメインページ) | - |
デバイス画面をインタラクティブにするには、`DROIDGROUND_SCRCPY_CONTROL_ENABLED=true` を設定して DroidGround を再起動します。画面をクリックまたはタップしてフォーカスし、クリック、ドラッグ、スワイプ、マルチタッチポイントの使用、マウスホイールでのスクロール、または入力を行います。右クリックまたは Escape キーで Android の戻る操作になります。Tab と Shift+Tab は画面からフォーカスを移動します。入力はチームモードを含め、デバイスを閲覧している全員で共有されます。デフォルトは引き続き閲覧専用画面です。テキスト入力は scrcpy の Android キーインジェクションを使用するため、文字のサポートはデバイスのキーボードマッピングに依存します。
`DROIDGROUND_IP_IFACE` は最初に完全一致を探し、見つからない場合は指定された値で _始まる_ 最初のインターフェースにフォールバックします。これは Docker がコンテナ内でネットワークインターフェースの **プレフィックス** しか指定できないためです。
画面ストリーミングはデフォルトで最大 1280 ピクセル、最大 60 fps、4 Mbps に設定され、エンコード、ネットワーク、ブラウザの負荷を軽減します。これは埋め込みデバイスビューの応答性と引き換えに、細部の一部を犠牲にします。以前のフル解像度の品質設定に戻すには、`DROIDGROUND_SCRCPY_MAX_SIZE=0` と `DROIDGROUND_SCRCPY_VIDEO_BIT_RATE=10000000` を設定します。低速な接続やブラウザの場合は、最大サイズ `1024`、`30` fps、`2000000` ビット毎秒を試してください。これらの設定を変更した後は DroidGround を再起動してください。
ブラウザは利用可能な場合は WebCodecs を使用し、そうでない場合はソフトウェア H.264 デコーダーにフォールバックします。WebCodecs にはセキュアコンテキストが必要です: リモートデプロイには HTTPS を使用してください (localhost も機能します)。リモート IP またはホスト名でのプレーン HTTP はソフトウェアデコードを使用します。低速なビューアはビデオのバックログを蓄積する代わりに、新しいキーフレームにスキップします。1.5 秒以内にキーフレームが到着しない場合、DroidGround はビデオリフレッシュを要求します。これは ReDroid の `OMX.google.h264.encoder` など、定期的な I フレームが必ずしも独立してデコード可能な IDR フレームではないエンコーダーをサポートします。リフレッシュ要求はビューア間で共有され、全員の画面が一時的にリフレッシュされる場合があります。サーバーはビデオリフレッシュ用に内部 scrcpy コントロールチャネルを保持します。マウス、タッチ、キーボード入力、および自動画面ウェイクアップは `DROIDGROUND_SCRCPY_CONTROL_ENABLED` によって制御されたままです。基盤となるブラウザとビデオ設定については、[WebCodecs 仕様](https://www.w3.org/TR/webcodecs/#videodecoder-interface) と [scrcpy ビデオドキュメント](https://github.com/Genymobile/scrcpy/blob/master/doc/video.md) を参照してください。
`DROIDGROUND_NUM_TEAMS` 変数の使用は、内部的にアプリケーションの動作を若干変更します。このオプションが設定されている場合:
1. エクスプロイトサーバー機能が有効になり、各チームが **_チームトークン_** を介して独自の (非常にシンプルな) エクスプロイトサーバーを使用できるようになります。
2. エクスプロイトアプリをインストールして実行するには **_チームトークン_** が **必須** になります。インストールされた各アプリはチームに紐付けられ、他のチームはそれを実行できません。
これにより、フラグがネットワークリクエストを介して持ち出される可能性があるチャレンジで、同じ DroidGround インスタンスを複数のチームと共有できます。これは CTF コンペティションにおける **DroidGround のデプロイコストを大幅に削減** します。
さらに、値が `-1` に設定されている場合、いわゆる **無制限チーム** モードが有効になります。このモードでは、_概要_ ページで新しい **_チームトークン_** を生成するボタンが利用可能になります。このモードが有効な場合、すべての `DROIDGROUND_TEAM_TOKEN_<N>` 変数は無視されます。
## 🧩 ユースケース
DroidGround を使用できるいくつかの方法を以下に示します:
1. **隠されたアクティビティ**: 公開されていないアクティビティを見つけて起動し、フラグを確認します (プレイヤーのアプリにはダミーフラグが含まれています)。
2. **RCE**: アプリが RCE に対して脆弱で、フラグがデバイス上に保存されています。
3. **Frida インストルメンテーション**: メソッドをオーバーロードし、スクリプトを使用してプライベートメモリからフラグを抽出します。
## ⚙️ 使用方法
いくつかのサンプル _Docker Compose_ ファイルが [examples](https://github.com/secforce/droidground/blob/main/examples/apps) フォルダーに提供されています。これらは [DroidGround サンプルリポジトリ](https://github.com/SECFORCE/droidground-samples) のアプリを使用しており、すべての主要機能を紹介するために段階的に強化されます。また、独自の CTF をセットアップする方法を理解するための良い出発点でもあります。
起動時に _DroidGround_ は以下を実行します:
1. `adb` との接続をセットアップ
2. `DROIDGROUND_INIT_SCRIPTS_FOLDER` で指定されたフォルダーに `setup.sh` が存在する場合、それを実行します。このスクリプトは、ターゲットアプリのインストールや CTF を初期化するために必要なその他すべて (例: 既知の場所へのフラグの配置) に使用できます
3. (_Frida_ が有効な場合) インストールされているバージョンとデバイスのアーキテクチャに基づいて正しい `frida-server` をダウンロードして起動
4. ターゲットアプリ (`DROIDGROUND_APP_PACKAGE_NAME` で指定されたもの) を実行します。アプリがインストールされていない場合、_DroidGround_ は終了します。
5. _REST API_、_WebSocket_ サーバー、およびディスプレイストリーミングをセットアップ
以下はサンプルの `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"
```
本番デプロイ (実際の CTF) では、事前に定義された数の DroidGround インスタンスをプロビジョニングするか、ユーザーがインスタンスを起動できるようにする (制限付きで、または各チーム/ユーザーを特定のインスタンスに関連付ける) ことを望むかもしれません。このため、シンプルな [spawner の例](https://github.com/secforce/droidground/blob/main/examples/spawner) も追加しました。
あるいは、前述のように、フラグがネットワークリクエストを介して持ち出される可能性があるチャレンジを作成し、`DROIDGROUND_NUM_TEAMS` 環境変数を活用して複数のインスタンスを起動する (コストがかかる可能性がある) ことを避けることができます。[net-multi-step](https://github.com/secforce/droidground/blob/main/examples/apps/net-multi-step) フォルダーは、このタイプのチャレンジを提供する方法の良い例を提供します。
## 💡 ヒント
Android CTF をセットアップするためのいくつかの提案を以下に示します:
- **Frida フルモード** を有効にする場合は注意してください。プレイヤーはデバイスを完全に制御できるようになります (そのため、[Frida ライブラリ](https://github.com/secforce/droidground/blob/main/library) で詳述されている **Frida ジェイルモード** を作成しました)。
- **ターミナル** を有効にする場合は注意してください。プレイヤーはデバイスを完全に制御できるようになります。
- **シャットダウン** 機能を有効にする場合は注意してください。
- フラグを UI で直接表示できるようにする予定の場合は、異なるインスタンス (チーム/プレイヤーごとに 1 つ) を起動する方法を見つけることをお勧めします。
本番環境に移行する前にセットアップをテストする際、ターゲットアプリの **攻撃面** を取得すると便利な場合があります。これはプレイヤーが見るべきものではありません。攻撃面を発見して分析することは彼らの仕事の一部だからです!
そのため、`/attackSurface` で到達可能な `GET` エンドポイントが提供され、起動時にランダムに生成されてログに出力されるトークン (`Authorization` ヘッダーの値として使用する必要があります) で保護されています (したがって、システム管理者のみがアクセスできます)。
ジェイルモードで独自の Frida スクリプトを使用したい場合は、それらを含むフォルダーを Docker コンテナにバインドマウントするだけです:
```yaml
volumes:
- <Frida library folder>:/droidground/library
```
利用可能なスクリプトのリストをアプリケーションに指示するために、`library.json` ファイル ([library](https://github.com/secforce/droidground/blob/main/library/library.json) にあるようなもの) が必要です。
## 🛠 開発
起動して実行するのはそれほど難しくないはずですが、開始する前に以下のツールがインストールされている必要があります:
- `frida` (_Frida_ を有効にする場合のみ)
- `node` (Node アプリなので、必要です!)
- `adb` (そう、デバイスと通信するために依存しています)
- _JDK_ (コンパニオンアプリをビルドするために必要です)
その後、以下を実行するだけです:
```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
```
その後、**env** 変数を設定して `npm run dev` を実行すれば準備完了です。ハッピー開発モード!
## 🤝 コントリビューション
プルリクエストを歓迎します! 大きな変更については、まず issue を開いて議論してください。新しい CTF ワークフローやチャレンジタイプのアイデアは特に歓迎します。
## 📚 クレジット
[Angelo Delicato](https://github.com/thelicato) [@SECFORCE](https://www.secforce.com) によって開発されました。
_server_ セクションは [@yume-chan](https://github.com/yume-chan/ya-webadb) による素晴らしい仕事に大きく依存しています。彼の素晴らしい仕事がなければ、このアプリは存在しなかったでしょう。
_companion_ アプリは [aya server](https://github.com/liriliri/aya/tree/master/server) に大きく基づいており、[scrcpy server](https://github.com/Genymobile/scrcpy) と同じように動作します。詳細は特定の [README](https://github.com/secforce/droidground/blob/main/companion/README.md) に記載されています。
## 🪪 ライセンス
_DroidGround_ は [GPL-3.0 LICENSE](https://github.com/SECFORCE/droidground/blob/main/LICENSE) の下でリリースされています