mirror of
https://github.com/GH05TCREW/pentestagent.git
synced 2026-03-08 06:44:11 +00:00
238 lines
6.3 KiB
Python
238 lines
6.3 KiB
Python
"""Interface utilities for GhostCrew."""
|
|
|
|
from typing import Any, Optional
|
|
|
|
from rich.console import Console
|
|
from rich.panel import Panel
|
|
from rich.table import Table
|
|
|
|
console = Console()
|
|
|
|
|
|
# ASCII Art Banner
|
|
ASCII_BANNER = r"""
|
|
('-. .-. .-') .-') _ _ .-') ('-. (`\ .-') /`
|
|
( OO ) / ( OO ). ( OO) ) ( \( -O ) _( OO) `.( OO ),'
|
|
,----. ,--. ,--. .-'),-----. (_)---\_)/ '._ .-----. ,------. (,------.,--./ .--.
|
|
' .-./-') | | | |( OO' .-. '/ _ | |'--...__)' .--./ | /`. ' | .---'| | |
|
|
| |_( O- )| .| |/ | | | |\ :` `. '--. .--'| |('-. | / | | | | | | | |,
|
|
| | .--, \| |\_) | |\| | '..`''.) | | /_) |OO )| |_.' |(| '--. | |.'.| |_)
|
|
(| | '. (_/| .-. | \ | | | |.-._) \ | | || |`-'| | . '.' | .--' | |
|
|
| '--' | | | | | `' '-' '\ / | | (_' '--'\ | |\ \ | `---.| ,'. |
|
|
`------' `--' `--' `-----' `-----' `--' `-----' `--' '--' `------''--' '--'
|
|
"""
|
|
|
|
|
|
def print_banner():
|
|
"""Print the GhostCrew banner."""
|
|
console.print(f"[bold white]{ASCII_BANNER}[/]")
|
|
console.print(
|
|
"[bold white]====================== GHOSTCREW =======================[/]"
|
|
)
|
|
console.print(
|
|
"[dim white] AI Penetration Testing Agents v0.2.0[/dim white]\n"
|
|
)
|
|
|
|
|
|
def format_finding(
|
|
title: str,
|
|
severity: str,
|
|
target: str,
|
|
description: str,
|
|
evidence: str = "",
|
|
impact: str = "",
|
|
remediation: str = "",
|
|
) -> Panel:
|
|
"""
|
|
Format a security finding for display.
|
|
|
|
Args:
|
|
title: Finding title
|
|
severity: Severity level
|
|
target: Affected target
|
|
description: Description of the finding
|
|
evidence: Proof/evidence
|
|
impact: Potential impact
|
|
remediation: How to fix
|
|
|
|
Returns:
|
|
Rich Panel with formatted finding
|
|
"""
|
|
severity_colors = {
|
|
"critical": "red bold",
|
|
"high": "red",
|
|
"medium": "yellow",
|
|
"low": "blue",
|
|
"informational": "dim",
|
|
}
|
|
|
|
color = severity_colors.get(severity.lower(), "white")
|
|
|
|
content = f"""
|
|
[bold]Target:[/] {target}
|
|
[{color}]Severity:[/{color}] [{color}]{severity.upper()}[/{color}]
|
|
|
|
[bold]Description:[/]
|
|
{description}
|
|
"""
|
|
|
|
if evidence:
|
|
content += f"\n[bold]Evidence:[/]\n{evidence}\n"
|
|
|
|
if impact:
|
|
content += f"\n[bold]Impact:[/]\n{impact}\n"
|
|
|
|
if remediation:
|
|
content += f"\n[bold]Remediation:[/]\n{remediation}\n"
|
|
|
|
return Panel(content, title=f"[bold]{title}[/]", border_style=color)
|
|
|
|
|
|
def format_tool_call(tool_call: Any) -> str:
|
|
"""
|
|
Format a tool call for display.
|
|
|
|
Args:
|
|
tool_call: The tool call object
|
|
|
|
Returns:
|
|
Formatted string
|
|
"""
|
|
name = tool_call.name if hasattr(tool_call, "name") else str(tool_call)
|
|
args = tool_call.arguments if hasattr(tool_call, "arguments") else {}
|
|
|
|
# Truncate long arguments
|
|
args_str = str(args)
|
|
if len(args_str) > 100:
|
|
args_str = args_str[:100] + "..."
|
|
|
|
return f"[bold yellow]⚡ Tool:[/] {name}\n[dim]{args_str}[/dim]"
|
|
|
|
|
|
def print_status(
|
|
target: Optional[str] = None,
|
|
scope: Optional[list] = None,
|
|
agent_state: str = "idle",
|
|
tools_count: int = 0,
|
|
findings_count: int = 0,
|
|
):
|
|
"""
|
|
Print current status information.
|
|
|
|
Args:
|
|
target: Current target
|
|
scope: Current scope
|
|
agent_state: Agent state
|
|
tools_count: Number of loaded tools
|
|
findings_count: Number of findings
|
|
"""
|
|
table = Table(title="GhostCrew Status", show_header=False)
|
|
table.add_column("Property", style="cyan")
|
|
table.add_column("Value", style="white")
|
|
|
|
table.add_row("Target", target or "Not set")
|
|
table.add_row("Scope", ", ".join(scope) if scope else "Not set")
|
|
table.add_row("Agent State", agent_state)
|
|
table.add_row("Tools Loaded", str(tools_count))
|
|
table.add_row("Findings", str(findings_count))
|
|
|
|
console.print(table)
|
|
|
|
|
|
def format_scan_progress(current: int, total: int, current_item: str) -> str:
|
|
"""
|
|
Format scan progress for display.
|
|
|
|
Args:
|
|
current: Current item number
|
|
total: Total items
|
|
current_item: Current item being scanned
|
|
|
|
Returns:
|
|
Formatted progress string
|
|
"""
|
|
percentage = (current / total * 100) if total > 0 else 0
|
|
bar_width = 30
|
|
filled = int(bar_width * current / total) if total > 0 else 0
|
|
bar = "█" * filled + "░" * (bar_width - filled)
|
|
|
|
return f"[{bar}] {percentage:.1f}% ({current}/{total}) - {current_item}"
|
|
|
|
|
|
def truncate_output(output: str, max_lines: int = 50) -> str:
|
|
"""
|
|
Truncate long output for display.
|
|
|
|
Args:
|
|
output: Output to truncate
|
|
max_lines: Maximum number of lines
|
|
|
|
Returns:
|
|
Truncated output
|
|
"""
|
|
lines = output.split("\n")
|
|
|
|
if len(lines) <= max_lines:
|
|
return output
|
|
|
|
half = max_lines // 2
|
|
truncated = (
|
|
lines[:half]
|
|
+ [f"\n... ({len(lines) - max_lines} lines omitted) ...\n"]
|
|
+ lines[-half:]
|
|
)
|
|
|
|
return "\n".join(truncated)
|
|
|
|
|
|
def colorize_severity(severity: str) -> str:
|
|
"""
|
|
Add color to severity text.
|
|
|
|
Args:
|
|
severity: Severity level
|
|
|
|
Returns:
|
|
Colorized severity string
|
|
"""
|
|
colors = {
|
|
"critical": "[red bold]CRITICAL[/]",
|
|
"high": "[red]HIGH[/]",
|
|
"medium": "[yellow]MEDIUM[/]",
|
|
"low": "[blue]LOW[/]",
|
|
"informational": "[dim]INFO[/]",
|
|
"info": "[dim]INFO[/]",
|
|
}
|
|
|
|
return colors.get(severity.lower(), severity)
|
|
|
|
|
|
def format_command_output(
|
|
command: str, exit_code: int, stdout: str, stderr: str
|
|
) -> Panel:
|
|
"""
|
|
Format command output for display.
|
|
|
|
Args:
|
|
command: The command that was run
|
|
exit_code: Exit code
|
|
stdout: Standard output
|
|
stderr: Standard error
|
|
|
|
Returns:
|
|
Rich Panel with formatted output
|
|
"""
|
|
success = exit_code == 0
|
|
border_color = "green" if success else "red"
|
|
|
|
content = f"[bold]Command:[/] {command}\n"
|
|
content += f"[bold]Exit Code:[/] {exit_code}\n"
|
|
|
|
if stdout:
|
|
content += f"\n[bold]Output:[/]\n{truncate_output(stdout)}"
|
|
|
|
if stderr:
|
|
content += f"\n[bold red]Errors:[/]\n{truncate_output(stderr)}"
|
|
|
|
return Panel(content, title="Command Result", border_style=border_color)
|