Files
Operator 0799bfbae8 Initial public portfolio release
Sanitized version of red team infrastructure automation platform.
Operational content (implant pipelines, lures, credential capture)
replaced with documented stubs. Architecture and infrastructure
automation code intact.
2026-06-23 16:12:14 -04:00

247 lines
9.3 KiB
Python

#!/usr/bin/env python3
"""
Common naming utilities for C2itall deployments
Provides consistent naming options across all deployment types
"""
import os
import glob
from utils.common import COLORS
def get_existing_deployments():
"""Get list of existing deployments from deployment info files"""
try:
info_files = glob.glob("logs/deployment_info_*.txt")
deployments = []
for info_file in info_files:
try:
deployment_info = {}
with open(info_file, 'r') as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if ": " in line and not line.startswith("-"):
parts = line.split(": ", 1)
if len(parts) == 2:
key, value = parts
deployment_info[key] = value
if deployment_info.get('deployment_id'):
deployments.append(deployment_info)
except Exception as e:
continue # Skip problematic files
return deployments
except Exception as e:
return []
def select_deployment_for_naming(exclude_types=None, current_deployment_id=None):
"""
Allow user to select an existing deployment to base naming on
Args:
exclude_types: List of deployment types to exclude (e.g., ['attack_box'])
current_deployment_id: Current deployment ID to exclude from list
"""
deployments = get_existing_deployments()
if not deployments:
print(f"{COLORS['YELLOW']}No existing deployments found{COLORS['RESET']}")
return None
print(f"\n{COLORS['CYAN']}Existing Deployments:{COLORS['RESET']}")
print(f"{COLORS['CYAN']}==================={COLORS['RESET']}")
# Filter deployments based on criteria
filtered_deployments = []
for deployment in deployments:
deployment_id = deployment.get('deployment_id', 'unknown')
# Skip current deployment
if current_deployment_id and deployment_id == current_deployment_id:
continue
# Skip excluded types
deployment_type = deployment.get('deployment_type', 'unknown')
if exclude_types and deployment_type in exclude_types:
continue
# Check if this is an attack box deployment (legacy check)
is_attack_box = (
deployment.get('deployment_type') == 'attack_box' or
deployment.get('attack_box_deployment') == 'True' or
deployment.get('attack_box_name')
)
if exclude_types and 'attack_box' in exclude_types and is_attack_box:
continue
filtered_deployments.append(deployment)
if not filtered_deployments:
print(f"{COLORS['YELLOW']}No suitable deployments found for naming{COLORS['RESET']}")
return None
# Display available deployments
for i, deployment in enumerate(filtered_deployments, 1):
deployment_id = deployment.get('deployment_id', 'unknown')
provider = deployment.get('provider', 'unknown')
domain = deployment.get('domain', 'N/A')
deployment_type = deployment.get('deployment_type', 'unknown')
print(f"{i}. {deployment_id}")
print(f" Type: {deployment_type}")
print(f" Provider: {provider}")
print(f" Domain: {domain}")
# Show instance names if available
instances = []
if deployment.get('redirector_name'):
instances.append(f"Redirector: {deployment.get('redirector_name')}")
if deployment.get('c2_name'):
instances.append(f"C2: {deployment.get('c2_name')}")
if deployment.get('tracker_name'):
instances.append(f"Tracker: {deployment.get('tracker_name')}")
if deployment.get('attack_box_name'):
instances.append(f"Attack Box: {deployment.get('attack_box_name')}")
if instances:
print(f" Instances: {', '.join(instances)}")
print()
# Get user selection
while True:
try:
choice = input(f"Select deployment (1-{len(filtered_deployments)}) or 'c' to cancel: ").strip()
if choice.lower() == 'c':
return None
choice_num = int(choice)
if 1 <= choice_num <= len(filtered_deployments):
selected = filtered_deployments[choice_num - 1]
return selected.get('deployment_id')
else:
print(f"{COLORS['RED']}Invalid choice. Please try again.{COLORS['RESET']}")
except ValueError:
print(f"{COLORS['RED']}Invalid input. Please enter a number or 'c'.{COLORS['RESET']}")
def get_deployment_name_with_options(deployment_type, deployment_id, prefix="", existing_name=None):
"""
Get deployment name with multiple naming options
Args:
deployment_type: Type of deployment (c2, redirector, tracker, attack_box, etc.)
deployment_id: Current deployment ID
prefix: Prefix for the name (e.g., 'r-', 'c-', 'a-', etc.)
existing_name: Existing name if updating
Returns:
Chosen name for the deployment
"""
print(f"\n{COLORS['BLUE']}{deployment_type.title()} Naming Options:{COLORS['RESET']}")
print(f"1) Auto-generate name ({prefix}{deployment_id})")
print(f"2) Name after existing deployment")
print(f"3) Custom name")
if existing_name:
print(f"4) Keep current name ({existing_name})")
default_choice = "4"
else:
default_choice = "1"
naming_choice = input(f"Select naming option [{default_choice}]: ").strip() or default_choice
if naming_choice == "1":
# Auto-generate using deployment ID
chosen_name = f"{prefix}{deployment_id}"
print(f"Using auto-generated name: {COLORS['CYAN']}{chosen_name}{COLORS['RESET']}")
elif naming_choice == "2":
# Name after existing deployment
# Exclude attack boxes when naming other types, but allow other types when naming attack boxes
exclude_types = ['attack_box'] if deployment_type != 'attack_box' else []
selected_deployment_id = select_deployment_for_naming(
exclude_types=exclude_types,
current_deployment_id=deployment_id
)
if selected_deployment_id:
chosen_name = f"{prefix}{selected_deployment_id}"
print(f"{deployment_type.title()} will be named: {COLORS['CYAN']}{chosen_name}{COLORS['RESET']}")
print(f"This associates it with deployment: {COLORS['YELLOW']}{selected_deployment_id}{COLORS['RESET']}")
else:
print(f"{COLORS['YELLOW']}No deployment selected, using auto-generated name{COLORS['RESET']}")
chosen_name = f"{prefix}{deployment_id}"
elif naming_choice == "3":
# Custom name
while True:
custom_name = input(f"Enter custom {deployment_type} name: ").strip()
if custom_name:
# Ensure it starts with the correct prefix for consistency
if prefix and not custom_name.startswith(prefix):
chosen_name = f"{prefix}{custom_name}"
print(f"Prefixed with '{prefix}': {COLORS['CYAN']}{chosen_name}{COLORS['RESET']}")
else:
chosen_name = custom_name
break
else:
print(f"{COLORS['RED']}Name cannot be empty. Please try again.{COLORS['RESET']}")
elif naming_choice == "4" and existing_name:
# Keep existing name
chosen_name = existing_name
print(f"Keeping current name: {COLORS['CYAN']}{chosen_name}{COLORS['RESET']}")
else:
# Default fallback
print(f"{COLORS['YELLOW']}Invalid choice, using auto-generated name{COLORS['RESET']}")
chosen_name = f"{prefix}{deployment_id}"
return chosen_name
def show_naming_relationship(name, deployment_id, deployment_type):
"""Show the relationship between the chosen name and deployment"""
if not name:
return
# Determine prefix based on deployment type
prefix_map = {
'redirector': 'r-',
'c2': 's-', # s for server
'tracker': 't-',
'attack_box': 'a-',
'payload': 'p-',
'webrunner': 'wr-',
}
expected_prefix = prefix_map.get(deployment_type, '')
if expected_prefix and name.startswith(expected_prefix):
target_deployment = name[len(expected_prefix):] # Remove prefix
if target_deployment != deployment_id:
return {
'target_deployment': target_deployment,
'relationship_text': f"Named after deployment: {target_deployment}",
'purpose_text': f"This {deployment_type} supports the {target_deployment} engagement"
}
return None
def get_deployment_type_prefix(deployment_type):
"""Get the standard prefix for a deployment type"""
prefix_map = {
'redirector': 'r-',
'c2': 's-', # s for server
'tracker': 't-',
'attack_box': 'a-',
'payload': 'p-',
'phishing': 'p-',
'webrunner': 'wr-',
}
return prefix_map.get(deployment_type, '')