# web_utils/orchestrator_utils.py """ Orchestrator management utilities. Handles attack execution, scanning, and credential management. """ from __future__ import annotations import json import html import importlib from datetime import datetime from typing import Any, Dict, Optional import logging from logger import Logger logger = Logger(name="orchestrator_utils.py", level=logging.DEBUG) class OrchestratorUtils: """Utilities for orchestrator and attack management.""" def __init__(self, shared_data): self.logger = logger self.shared_data = shared_data def execute_manual_attack(self, params): """Execute a manual attack on a specific target.""" try: ip = params['ip'] port = params['port'] action_class = params['action'] self.shared_data.bjorn_status_text2 = "" self.logger.info(f"Received request to execute {action_class} on {ip}:{port}") # Load actions self._load_actions() action_instance = next((action for action in self.shared_data.actions if action.action_name == action_class), None) if action_instance is None: raise Exception(f"Action class {action_class} not found") current_data = self.shared_data.read_data() row = next((r for r in current_data if r["IPs"] == ip), None) if row is None: raise Exception(f"No data found for IP: {ip}") action_key = action_instance.action_name self.logger.info(f"Executing {action_key} on {ip}:{port}") result = action_instance.execute(ip, port, row, action_key) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") if result == 'success': row[action_key] = f'success_{timestamp}' self.logger.info(f"Action {action_key} executed successfully on {ip}:{port}") else: row[action_key] = f'failed_{timestamp}' self.logger.error(f"Action {action_key} failed on {ip}:{port}") self.shared_data.write_data(current_data) # Update status after completion self.shared_data.bjorn_orch_status = "IDLE" self.shared_data.bjorn_status_text2 = "Waiting for instructions..." return {"status": "success", "message": "Manual attack executed"} except Exception as e: self.logger.error(f"Error executing manual attack: {e}") self.shared_data.bjorn_orch_status = "IDLE" self.shared_data.bjorn_status_text2 = "Waiting for instructions..." return {"status": "error", "message": str(e)} def execute_manual_scan(self): """Execute a manual network scan.""" try: # Import network scanner module = importlib.import_module('actions.scanning') scanner_class = getattr(module, getattr(module, 'b_class')) network_scanner = scanner_class(self.shared_data) # Update status self.shared_data.bjorn_orch_status = "NetworkScanner" self.shared_data.bjorn_status_text2 = "Manual scan..." # Execute scan network_scanner.scan() # Reset status self.shared_data.bjorn_orch_status = "IDLE" self.shared_data.bjorn_status_text2 = "Waiting for instructions..." return {"status": "success", "message": "Network scan completed"} except Exception as e: self.logger.error(f"Error executing manual scan: {e}") self.shared_data.bjorn_orch_status = "IDLE" self.shared_data.bjorn_status_text2 = "Waiting for instructions..." return {"status": "error", "message": str(e)} def start_orchestrator(self): """Start the orchestrator.""" try: bjorn_instance = self.shared_data.bjorn_instance self.shared_data.manual_mode = False self.shared_data.orchestrator_should_exit = False bjorn_instance.start_orchestrator() return {"status": "success", "message": "Orchestrator starting..."} except Exception as e: self.logger.error(f"Error starting orchestrator: {e}") return {"status": "error", "message": str(e)} def stop_orchestrator(self): """Stop the orchestrator.""" try: bjorn_instance = self.shared_data.bjorn_instance self.shared_data.manual_mode = False bjorn_instance.stop_orchestrator() self.shared_data.orchestrator_should_exit = True return {"status": "success", "message": "Orchestrator stopping..."} except Exception as e: self.logger.error(f"Error stopping orchestrator: {e}") return {"status": "error", "message": str(e)} def serve_credentials_data(self, handler): """Serve credentials data as HTML.""" try: creds = self.shared_data.db.list_creds_grouped() html_content = self._html_from_creds(creds) handler.send_response(200) handler.send_header("Content-type", "text/html") handler.end_headers() handler.wfile.write(html_content.encode("utf-8")) except Exception as e: handler.send_response(500) handler.send_header("Content-type", "application/json") handler.end_headers() handler.wfile.write(json.dumps({"status": "error", "message": str(e)}).encode("utf-8")) def _html_from_creds(self, rows): """Generate HTML table from credentials data.""" out = ['
'] # Group by service by_service = {} for r in rows: by_service.setdefault(r["service"], []).append(r) for svc, items in by_service.items(): out.append(f"

{html.escape(svc)}.db

") out.append('') for h in ["MAC", "IP", "Hostname", "User", "Password", "Port", "Database", "Last Seen"]: out.append(f"") out.append("") for r in items: out.append("") out.append(f"") out.append(f"") out.append(f"") out.append(f"") out.append(f"") out.append(f"") out.append(f"") out.append(f"") out.append("") out.append("
{h}
{html.escape(r.get('mac_address') or '')}{html.escape(r.get('ip') or '')}{html.escape(r.get('hostname') or '')}{html.escape(r.get('user') or '')}{html.escape(r.get('password') or '')}{html.escape(str(r.get('port') or ''))}{html.escape(r.get('database') or '')}{html.escape(r.get('last_seen') or '')}
") out.append("
") return "\n".join(out) def _load_actions(self): """Load actions from database.""" if self.shared_data.actions is None or self.shared_data.standalone_actions is None: self.shared_data.actions, self.shared_data.standalone_actions = [], [] for action in self.shared_data.db.list_actions(): module_name = action["b_module"] if module_name == 'scanning': self._load_scanner(module_name) else: self._load_action(module_name, action) def _load_scanner(self, module_name): """Load the network scanner.""" module = importlib.import_module(f'actions.{module_name}') b_class = getattr(module, 'b_class') self.shared_data.network_scanner = getattr(module, b_class)(self.shared_data) def _load_action(self, module_name, action): """Load an action from the actions directory.""" module = importlib.import_module(f'actions.{module_name}') try: b_class = action["b_class"] action_instance = getattr(module, b_class)(self.shared_data) action_instance.action_name = b_class action_instance.port = action.get("b_port") action_instance.b_parent_action = action.get("b_parent") if action_instance.port == 0: self.shared_data.standalone_actions.append(action_instance) else: self.shared_data.actions.append(action_instance) except AttributeError as e: self.logger.error(f"Module {module_name} is missing required attributes: {e}")