first commit
This commit is contained in:
301
pentestgpt.py
Normal file
301
pentestgpt.py
Normal file
@@ -0,0 +1,301 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
PentestGPT Tab Implementation
|
||||
Handles the PentestGPT interface and controls for DarkHal 2.0
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, messagebox, filedialog
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
class PentestGPTTab:
|
||||
"""PentestGPT tab with penetration testing agent controls."""
|
||||
|
||||
def __init__(self, parent: ttk.Frame, settings_manager, main_app=None):
|
||||
self.parent = parent
|
||||
self.settings = settings_manager
|
||||
self.main_app = main_app
|
||||
self.pentestgpt_process = None
|
||||
|
||||
# Create main frame
|
||||
self.main_frame = ttk.Frame(parent)
|
||||
self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
|
||||
# Create PentestGPT interface
|
||||
self._create_pentestgpt_interface()
|
||||
|
||||
def _create_pentestgpt_interface(self):
|
||||
"""Create PentestGPT control and configuration interface."""
|
||||
|
||||
# PentestGPT configuration frame
|
||||
config_frame = ttk.LabelFrame(self.main_frame, text="PentestGPT Configuration", padding=10)
|
||||
config_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# Configuration options
|
||||
options_frame = ttk.Frame(config_frame)
|
||||
options_frame.pack(fill=tk.X, pady=10)
|
||||
|
||||
# Model selection
|
||||
ttk.Label(options_frame, text="Model:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||
self.pentestgpt_model_var = tk.StringVar(value="gpt-4")
|
||||
model_combo = ttk.Combobox(options_frame, textvariable=self.pentestgpt_model_var,
|
||||
values=["gpt-4", "gpt-3.5-turbo", "claude-3", "local-llm"], width=15)
|
||||
model_combo.grid(row=0, column=1, padx=10)
|
||||
|
||||
# Target type
|
||||
ttk.Label(options_frame, text="Target Type:").grid(row=0, column=2, sticky=tk.W, padx=(20, 0))
|
||||
self.target_type_var = tk.StringVar(value="web")
|
||||
target_combo = ttk.Combobox(options_frame, textvariable=self.target_type_var,
|
||||
values=["web", "network", "mobile", "cloud", "iot"], width=15)
|
||||
target_combo.grid(row=0, column=3, padx=10)
|
||||
|
||||
# Scan depth
|
||||
ttk.Label(options_frame, text="Scan Depth:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
self.scan_depth_var = tk.StringVar(value="medium")
|
||||
depth_combo = ttk.Combobox(options_frame, textvariable=self.scan_depth_var,
|
||||
values=["light", "medium", "deep", "comprehensive"], width=15)
|
||||
depth_combo.grid(row=1, column=1, padx=10)
|
||||
|
||||
# Output directory
|
||||
ttk.Label(options_frame, text="Output Dir:").grid(row=1, column=2, sticky=tk.W, padx=(20, 0))
|
||||
self.output_dir_var = tk.StringVar(value="./pentest_results")
|
||||
ttk.Entry(options_frame, textvariable=self.output_dir_var, width=25).grid(row=1, column=3, padx=(10, 5))
|
||||
ttk.Button(options_frame, text="Browse", command=self._browse_output_dir).grid(row=1, column=4, padx=5)
|
||||
|
||||
# API Configuration
|
||||
api_frame = ttk.LabelFrame(config_frame, text="API Configuration", padding=5)
|
||||
api_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# OpenAI API Key
|
||||
ttk.Label(api_frame, text="OpenAI API Key:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||
self.openai_key_var = tk.StringVar()
|
||||
ttk.Entry(api_frame, textvariable=self.openai_key_var, show="*", width=40).grid(row=0, column=1, padx=10)
|
||||
|
||||
# Claude API Key
|
||||
ttk.Label(api_frame, text="Claude API Key:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
self.claude_key_var = tk.StringVar()
|
||||
ttk.Entry(api_frame, textvariable=self.claude_key_var, show="*", width=40).grid(row=1, column=1, padx=10)
|
||||
|
||||
# Control buttons
|
||||
control_frame = ttk.Frame(config_frame)
|
||||
control_frame.pack(fill=tk.X, pady=10)
|
||||
|
||||
self.pentestgpt_start_btn = ttk.Button(control_frame, text="Start PentestGPT",
|
||||
command=self._start_pentestgpt)
|
||||
self.pentestgpt_start_btn.pack(side=tk.LEFT, padx=5)
|
||||
|
||||
self.pentestgpt_stop_btn = ttk.Button(control_frame, text="Stop PentestGPT",
|
||||
command=self._stop_pentestgpt, state="disabled")
|
||||
self.pentestgpt_stop_btn.pack(side=tk.LEFT, padx=5)
|
||||
|
||||
# Configuration management
|
||||
config_btn_frame = ttk.Frame(control_frame)
|
||||
config_btn_frame.pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
ttk.Button(config_btn_frame, text="Save Config",
|
||||
command=self._save_pentestgpt_config).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(config_btn_frame, text="Load Config",
|
||||
command=self._load_pentestgpt_config).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(config_btn_frame, text="Configure",
|
||||
command=self._configure_pentestgpt).pack(side=tk.LEFT, padx=2)
|
||||
|
||||
# Output area
|
||||
output_frame = ttk.LabelFrame(self.main_frame, text="PentestGPT Output", padding=10)
|
||||
output_frame.pack(fill=tk.BOTH, expand=True, pady=10)
|
||||
|
||||
self.pentestgpt_output = tk.Text(output_frame, height=20, wrap=tk.WORD)
|
||||
pentestgpt_scrollbar = ttk.Scrollbar(output_frame, orient=tk.VERTICAL, command=self.pentestgpt_output.yview)
|
||||
self.pentestgpt_output.configure(yscrollcommand=pentestgpt_scrollbar.set)
|
||||
self.pentestgpt_output.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||
pentestgpt_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
|
||||
# Status bar
|
||||
self.pentestgpt_status_var = tk.StringVar(value="PentestGPT Status: Ready")
|
||||
ttk.Label(output_frame, textvariable=self.pentestgpt_status_var).pack(anchor=tk.W, pady=(5, 0))
|
||||
|
||||
def _start_pentestgpt(self):
|
||||
"""Start PentestGPT process."""
|
||||
self.pentestgpt_output.insert(tk.END, "Starting PentestGPT...\n")
|
||||
self.pentestgpt_output.insert(tk.END, f"Model: {self.pentestgpt_model_var.get()}\n")
|
||||
self.pentestgpt_output.insert(tk.END, f"Target Type: {self.target_type_var.get()}\n")
|
||||
self.pentestgpt_output.insert(tk.END, f"Scan Depth: {self.scan_depth_var.get()}\n\n")
|
||||
|
||||
# Check if PentestGPT is available
|
||||
pentestgpt_path = Path("experimental_agent/PentestGPT")
|
||||
if not pentestgpt_path.exists():
|
||||
self.pentestgpt_output.insert(tk.END, "Error: PentestGPT not found in experimental_agent directory\n")
|
||||
self.pentestgpt_status_var.set("PentestGPT Status: Error - Not Found")
|
||||
return
|
||||
|
||||
# This would start the actual PentestGPT process
|
||||
# For now, we'll simulate the startup
|
||||
self.pentestgpt_output.insert(tk.END, "PentestGPT started successfully!\n")
|
||||
self.pentestgpt_output.insert(tk.END, "Ready for penetration testing commands...\n\n")
|
||||
|
||||
# Update button states
|
||||
self.pentestgpt_start_btn.config(state="disabled")
|
||||
self.pentestgpt_stop_btn.config(state="normal")
|
||||
self.pentestgpt_status_var.set("PentestGPT Status: Running")
|
||||
|
||||
def _stop_pentestgpt(self):
|
||||
"""Stop PentestGPT process."""
|
||||
if self.pentestgpt_process:
|
||||
self.pentestgpt_process.terminate()
|
||||
self.pentestgpt_process = None
|
||||
|
||||
self.pentestgpt_output.insert(tk.END, "PentestGPT stopped.\n\n")
|
||||
|
||||
# Update button states
|
||||
self.pentestgpt_start_btn.config(state="normal")
|
||||
self.pentestgpt_stop_btn.config(state="disabled")
|
||||
self.pentestgpt_status_var.set("PentestGPT Status: Stopped")
|
||||
|
||||
def _browse_output_dir(self):
|
||||
"""Browse for output directory."""
|
||||
directory = filedialog.askdirectory()
|
||||
if directory:
|
||||
self.output_dir_var.set(directory)
|
||||
|
||||
def _save_pentestgpt_config(self):
|
||||
"""Save PentestGPT configuration."""
|
||||
config = {
|
||||
"model": self.pentestgpt_model_var.get(),
|
||||
"target_type": self.target_type_var.get(),
|
||||
"scan_depth": self.scan_depth_var.get(),
|
||||
"output_dir": self.output_dir_var.get(),
|
||||
"openai_key": self.openai_key_var.get(),
|
||||
"claude_key": self.claude_key_var.get()
|
||||
}
|
||||
|
||||
try:
|
||||
config_file = Path("pentestgpt_config.json")
|
||||
import json
|
||||
with open(config_file, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
self.pentestgpt_output.insert(tk.END, f"Configuration saved to {config_file}\n")
|
||||
except Exception as e:
|
||||
messagebox.showerror("Save Error", f"Failed to save configuration: {str(e)}")
|
||||
|
||||
def _load_pentestgpt_config(self):
|
||||
"""Load PentestGPT configuration."""
|
||||
try:
|
||||
config_file = Path("pentestgpt_config.json")
|
||||
if not config_file.exists():
|
||||
messagebox.showwarning("Load Error", "No configuration file found")
|
||||
return
|
||||
|
||||
import json
|
||||
with open(config_file, 'r') as f:
|
||||
config = json.load(f)
|
||||
|
||||
# Apply configuration
|
||||
self.pentestgpt_model_var.set(config.get("model", "gpt-4"))
|
||||
self.target_type_var.set(config.get("target_type", "web"))
|
||||
self.scan_depth_var.set(config.get("scan_depth", "medium"))
|
||||
self.output_dir_var.set(config.get("output_dir", "./pentest_results"))
|
||||
self.openai_key_var.set(config.get("openai_key", ""))
|
||||
self.claude_key_var.set(config.get("claude_key", ""))
|
||||
|
||||
self.pentestgpt_output.insert(tk.END, f"Configuration loaded from {config_file}\n")
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("Load Error", f"Failed to load configuration: {str(e)}")
|
||||
|
||||
def _configure_pentestgpt(self):
|
||||
"""Open PentestGPT configuration dialog."""
|
||||
PentestGPTConfigDialog(self.parent, self)
|
||||
|
||||
|
||||
class PentestGPTConfigDialog:
|
||||
"""Dialog for configuring PentestGPT API keys and settings."""
|
||||
|
||||
def __init__(self, parent, pentestgpt_tab):
|
||||
self.pentestgpt_tab = pentestgpt_tab
|
||||
self.dialog = tk.Toplevel(parent)
|
||||
self.dialog.title("PentestGPT Configuration")
|
||||
self.dialog.geometry("500x400")
|
||||
self.dialog.transient(parent)
|
||||
self.dialog.grab_set()
|
||||
|
||||
# Create configuration interface
|
||||
self._create_config_interface()
|
||||
|
||||
# Center dialog
|
||||
self.dialog.update_idletasks()
|
||||
x = (self.dialog.winfo_screenwidth() // 2) - (self.dialog.winfo_width() // 2)
|
||||
y = (self.dialog.winfo_screenheight() // 2) - (self.dialog.winfo_height() // 2)
|
||||
self.dialog.geometry(f"+{x}+{y}")
|
||||
|
||||
def _create_config_interface(self):
|
||||
"""Create the configuration interface."""
|
||||
main_frame = ttk.Frame(self.dialog)
|
||||
main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
|
||||
|
||||
# API Keys section
|
||||
api_frame = ttk.LabelFrame(main_frame, text="API Configuration", padding=10)
|
||||
api_frame.pack(fill=tk.X, pady=(0, 20))
|
||||
|
||||
# OpenAI API Key
|
||||
ttk.Label(api_frame, text="OpenAI API Key:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||
self.openai_entry = ttk.Entry(api_frame, show="*", width=40)
|
||||
self.openai_entry.grid(row=0, column=1, padx=(10, 0), pady=5)
|
||||
self.openai_entry.insert(0, self.pentestgpt_tab.openai_key_var.get())
|
||||
|
||||
# Claude API Key
|
||||
ttk.Label(api_frame, text="Claude API Key:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
self.claude_entry = ttk.Entry(api_frame, show="*", width=40)
|
||||
self.claude_entry.grid(row=1, column=1, padx=(10, 0), pady=5)
|
||||
self.claude_entry.insert(0, self.pentestgpt_tab.claude_key_var.get())
|
||||
|
||||
# Advanced Settings section
|
||||
advanced_frame = ttk.LabelFrame(main_frame, text="Advanced Settings", padding=10)
|
||||
advanced_frame.pack(fill=tk.X, pady=(0, 20))
|
||||
|
||||
# Max concurrent scans
|
||||
ttk.Label(advanced_frame, text="Max Concurrent Scans:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||
self.max_scans_var = tk.StringVar(value="3")
|
||||
ttk.Entry(advanced_frame, textvariable=self.max_scans_var, width=10).grid(row=0, column=1, padx=(10, 0), pady=5)
|
||||
|
||||
# Timeout settings
|
||||
ttk.Label(advanced_frame, text="Request Timeout (s):").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
self.timeout_var = tk.StringVar(value="30")
|
||||
ttk.Entry(advanced_frame, textvariable=self.timeout_var, width=10).grid(row=1, column=1, padx=(10, 0), pady=5)
|
||||
|
||||
# Buttons
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.pack(fill=tk.X, pady=(20, 0))
|
||||
|
||||
ttk.Button(button_frame, text="Save", command=self._save_config).pack(side=tk.RIGHT, padx=(10, 0))
|
||||
ttk.Button(button_frame, text="Cancel", command=self._cancel).pack(side=tk.RIGHT)
|
||||
|
||||
def _save_config(self):
|
||||
"""Save the configuration."""
|
||||
try:
|
||||
# Update the main tab variables
|
||||
self.pentestgpt_tab.openai_key_var.set(self.openai_entry.get())
|
||||
self.pentestgpt_tab.claude_key_var.set(self.claude_entry.get())
|
||||
|
||||
# Save to file
|
||||
config = {
|
||||
"openai_key": self.openai_entry.get(),
|
||||
"claude_key": self.claude_entry.get(),
|
||||
"max_scans": self.max_scans_var.get(),
|
||||
"timeout": self.timeout_var.get()
|
||||
}
|
||||
|
||||
import json
|
||||
config_file = Path("pentestgpt_advanced_config.json")
|
||||
with open(config_file, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
messagebox.showinfo("Success", "Configuration saved successfully!")
|
||||
self.dialog.destroy()
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("Save Error", f"Failed to save configuration: {str(e)}")
|
||||
|
||||
def _cancel(self):
|
||||
"""Cancel the configuration dialog."""
|
||||
self.dialog.destroy()
|
||||
Reference in New Issue
Block a user