v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
"""Offense category route - MSF server control, module search, sessions, browsing, execution."""
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
import threading
|
|
|
|
|
import uuid
|
|
|
|
|
from flask import Blueprint, render_template, request, jsonify, Response
|
|
|
|
|
from web.auth import login_required
|
|
|
|
|
|
|
|
|
|
_running_jobs: dict = {} # job_id -> threading.Event (stop signal)
|
|
|
|
|
|
|
|
|
|
offense_bp = Blueprint('offense', __name__, url_prefix='/offense')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/')
|
|
|
|
|
@login_required
|
|
|
|
|
def index():
|
|
|
|
|
from core.menu import MainMenu
|
|
|
|
|
menu = MainMenu()
|
|
|
|
|
menu.load_modules()
|
|
|
|
|
modules = {k: v for k, v in menu.modules.items() if v.category == 'offense'}
|
|
|
|
|
return render_template('offense.html', modules=modules)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/status')
|
|
|
|
|
@login_required
|
|
|
|
|
def status():
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
"""Get MSF connection and server status."""
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
from core.msf import get_msf_manager
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
msf = get_msf_interface()
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
mgr = get_msf_manager()
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
connected = msf.is_connected
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
settings = mgr.get_settings()
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
# Check if server process is running
|
|
|
|
|
server_running, server_pid = mgr.detect_server()
|
|
|
|
|
|
|
|
|
|
result = {
|
|
|
|
|
'connected': connected,
|
|
|
|
|
'server_running': server_running,
|
|
|
|
|
'server_pid': server_pid,
|
|
|
|
|
'host': settings.get('host', '127.0.0.1'),
|
|
|
|
|
'port': settings.get('port', 55553),
|
|
|
|
|
'username': settings.get('username', 'msf'),
|
|
|
|
|
'ssl': settings.get('ssl', True),
|
|
|
|
|
'has_password': bool(settings.get('password', '')),
|
|
|
|
|
}
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
if connected:
|
|
|
|
|
try:
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
version = msf.manager.rpc.get_version()
|
|
|
|
|
result['version'] = version.get('version', '')
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return jsonify(result)
|
v2.2.0 — Full arsenal expansion: 16 new security modules
Add WiFi Audit, API Fuzzer, Cloud Scanner, Threat Intel, Log Correlator,
Steganography, Anti-Forensics, BLE Scanner, Forensics, RFID/NFC, Malware
Sandbox, Password Toolkit, Web Scanner, Report Engine, Net Mapper, and
C2 Framework. Each module includes CLI interface, Flask routes, and web
UI template. Also includes Go DNS server source + binary, IP Capture
service, SYN Flood, Gone Fishing mail server, and hack hijack modules
from v2.0 work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:16:31 -08:00
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'connected': False, 'server_running': False, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/connect', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def connect():
|
|
|
|
|
"""Connect to MSF RPC server."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
password = data.get('password', '').strip()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from core.msf import get_msf_manager
|
|
|
|
|
mgr = get_msf_manager()
|
|
|
|
|
settings = mgr.get_settings()
|
|
|
|
|
|
|
|
|
|
# Use provided password or saved one
|
|
|
|
|
pwd = password or settings.get('password', '')
|
|
|
|
|
if not pwd:
|
|
|
|
|
return jsonify({'ok': False, 'error': 'Password required'})
|
|
|
|
|
|
|
|
|
|
mgr.connect(pwd)
|
|
|
|
|
version = mgr.rpc.get_version() if mgr.rpc else {}
|
|
|
|
|
return jsonify({
|
|
|
|
|
'ok': True,
|
|
|
|
|
'version': version.get('version', 'Connected')
|
|
|
|
|
})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'ok': False, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/disconnect', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def disconnect():
|
|
|
|
|
"""Disconnect from MSF RPC server."""
|
|
|
|
|
try:
|
|
|
|
|
from core.msf import get_msf_manager
|
|
|
|
|
mgr = get_msf_manager()
|
|
|
|
|
mgr.disconnect()
|
|
|
|
|
return jsonify({'ok': True})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'ok': False, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/server/start', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def start_server():
|
|
|
|
|
"""Start the MSF RPC server."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from core.msf import get_msf_manager
|
|
|
|
|
mgr = get_msf_manager()
|
|
|
|
|
settings = mgr.get_settings()
|
|
|
|
|
|
|
|
|
|
username = data.get('username', '').strip() or settings.get('username', 'msf')
|
|
|
|
|
password = data.get('password', '').strip() or settings.get('password', '')
|
|
|
|
|
host = data.get('host', '').strip() or settings.get('host', '127.0.0.1')
|
|
|
|
|
port = int(data.get('port', 0) or settings.get('port', 55553))
|
|
|
|
|
use_ssl = data.get('ssl', settings.get('ssl', True))
|
|
|
|
|
|
|
|
|
|
if not password:
|
|
|
|
|
return jsonify({'ok': False, 'error': 'Password required to start server'})
|
|
|
|
|
|
|
|
|
|
# Save settings
|
|
|
|
|
mgr.save_settings(host, port, username, password, use_ssl)
|
|
|
|
|
|
|
|
|
|
# Kill existing server if running
|
|
|
|
|
is_running, _ = mgr.detect_server()
|
|
|
|
|
if is_running:
|
|
|
|
|
mgr.kill_server(use_sudo=False)
|
|
|
|
|
|
|
|
|
|
# Start server (no sudo on web — would hang waiting for password)
|
|
|
|
|
import sys
|
|
|
|
|
use_sudo = sys.platform != 'win32' and data.get('sudo', False)
|
|
|
|
|
ok = mgr.start_server(username, password, host, port, use_ssl, use_sudo=use_sudo)
|
|
|
|
|
|
|
|
|
|
if ok:
|
|
|
|
|
# Auto-connect after starting
|
|
|
|
|
try:
|
|
|
|
|
mgr.connect(password)
|
|
|
|
|
version = mgr.rpc.get_version() if mgr.rpc else {}
|
|
|
|
|
return jsonify({
|
|
|
|
|
'ok': True,
|
|
|
|
|
'message': 'Server started and connected',
|
|
|
|
|
'version': version.get('version', '')
|
|
|
|
|
})
|
|
|
|
|
except Exception:
|
|
|
|
|
return jsonify({'ok': True, 'message': 'Server started (connect manually)'})
|
|
|
|
|
else:
|
|
|
|
|
return jsonify({'ok': False, 'error': 'Failed to start server'})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'ok': False, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/server/stop', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def stop_server():
|
|
|
|
|
"""Stop the MSF RPC server."""
|
|
|
|
|
try:
|
|
|
|
|
from core.msf import get_msf_manager
|
|
|
|
|
mgr = get_msf_manager()
|
|
|
|
|
ok = mgr.kill_server(use_sudo=False)
|
|
|
|
|
return jsonify({'ok': ok})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'ok': False, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/settings', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def save_settings():
|
|
|
|
|
"""Save MSF connection settings."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
try:
|
|
|
|
|
from core.msf import get_msf_manager
|
|
|
|
|
mgr = get_msf_manager()
|
|
|
|
|
mgr.save_settings(
|
|
|
|
|
host=data.get('host', '127.0.0.1'),
|
|
|
|
|
port=int(data.get('port', 55553)),
|
|
|
|
|
username=data.get('username', 'msf'),
|
|
|
|
|
password=data.get('password', ''),
|
|
|
|
|
use_ssl=data.get('ssl', True),
|
|
|
|
|
)
|
|
|
|
|
return jsonify({'ok': True})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'ok': False, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/jobs')
|
|
|
|
|
@login_required
|
|
|
|
|
def list_jobs():
|
|
|
|
|
"""List running MSF jobs."""
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
|
|
|
|
msf = get_msf_interface()
|
|
|
|
|
if not msf.is_connected:
|
|
|
|
|
return jsonify({'jobs': {}, 'error': 'Not connected to MSF'})
|
|
|
|
|
jobs = msf.list_jobs()
|
|
|
|
|
return jsonify({'jobs': jobs})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'jobs': {}, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/jobs/<job_id>/stop', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def stop_job(job_id):
|
|
|
|
|
"""Stop a running MSF job."""
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
|
|
|
|
msf = get_msf_interface()
|
|
|
|
|
ok = msf.stop_job(job_id)
|
|
|
|
|
return jsonify({'ok': ok})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'ok': False, 'error': str(e)})
|
Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.
Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/search', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def search():
|
|
|
|
|
"""Search MSF modules (offline library first, then live if connected)."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
query = data.get('query', '').strip()
|
|
|
|
|
|
|
|
|
|
if not query:
|
|
|
|
|
return jsonify({'error': 'No search query provided'})
|
|
|
|
|
|
|
|
|
|
# Search offline library first
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_modules import search_modules as offline_search
|
|
|
|
|
results = offline_search(query, max_results=30)
|
|
|
|
|
modules = [{'path': r['path'], 'name': r.get('name', ''), 'description': r.get('description', '')} for r in results]
|
|
|
|
|
except Exception:
|
|
|
|
|
modules = []
|
|
|
|
|
|
|
|
|
|
# If no offline results and MSF is connected, try live search
|
|
|
|
|
if not modules:
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
|
|
|
|
msf = get_msf_interface()
|
|
|
|
|
if msf.is_connected:
|
|
|
|
|
live_results = msf.search_modules(query)
|
|
|
|
|
modules = [{'path': r, 'name': r.split('/')[-1] if isinstance(r, str) else '', 'description': ''} for r in live_results[:30]]
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return jsonify({'modules': modules})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/sessions')
|
|
|
|
|
@login_required
|
|
|
|
|
def sessions():
|
|
|
|
|
"""List active MSF sessions."""
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
|
|
|
|
msf = get_msf_interface()
|
|
|
|
|
if not msf.is_connected:
|
|
|
|
|
return jsonify({'sessions': {}, 'error': 'Not connected to MSF'})
|
|
|
|
|
|
|
|
|
|
sessions_data = msf.list_sessions()
|
|
|
|
|
# Convert session data to serializable format
|
|
|
|
|
result = {}
|
|
|
|
|
for sid, sinfo in sessions_data.items():
|
|
|
|
|
if isinstance(sinfo, dict):
|
|
|
|
|
result[str(sid)] = sinfo
|
|
|
|
|
else:
|
|
|
|
|
result[str(sid)] = {
|
|
|
|
|
'type': getattr(sinfo, 'type', ''),
|
|
|
|
|
'tunnel_peer': getattr(sinfo, 'tunnel_peer', ''),
|
|
|
|
|
'info': getattr(sinfo, 'info', ''),
|
|
|
|
|
'target_host': getattr(sinfo, 'target_host', ''),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return jsonify({'sessions': result})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'sessions': {}, 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/modules/<module_type>')
|
|
|
|
|
@login_required
|
|
|
|
|
def browse_modules(module_type):
|
|
|
|
|
"""Browse modules by type from offline library."""
|
|
|
|
|
page = request.args.get('page', 1, type=int)
|
|
|
|
|
per_page = 20
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_modules import get_modules_by_type
|
|
|
|
|
all_modules = get_modules_by_type(module_type)
|
|
|
|
|
|
|
|
|
|
start = (page - 1) * per_page
|
|
|
|
|
end = start + per_page
|
|
|
|
|
page_modules = all_modules[start:end]
|
|
|
|
|
|
|
|
|
|
modules = [{'path': m['path'], 'name': m.get('name', '')} for m in page_modules]
|
|
|
|
|
|
|
|
|
|
return jsonify({
|
|
|
|
|
'modules': modules,
|
|
|
|
|
'total': len(all_modules),
|
|
|
|
|
'page': page,
|
|
|
|
|
'has_more': end < len(all_modules),
|
|
|
|
|
})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return jsonify({'modules': [], 'error': str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/module/info', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def module_info():
|
|
|
|
|
"""Get module info."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
module_path = data.get('module_path', '').strip()
|
|
|
|
|
|
|
|
|
|
if not module_path:
|
|
|
|
|
return jsonify({'error': 'No module path provided'})
|
|
|
|
|
|
|
|
|
|
# Try offline library first
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_modules import get_module_info
|
|
|
|
|
info = get_module_info(module_path)
|
|
|
|
|
if info:
|
|
|
|
|
return jsonify({
|
|
|
|
|
'path': module_path,
|
|
|
|
|
'name': info.get('name', ''),
|
|
|
|
|
'description': info.get('description', ''),
|
|
|
|
|
'author': info.get('author', []),
|
|
|
|
|
'platforms': info.get('platforms', []),
|
|
|
|
|
'reliability': info.get('reliability', ''),
|
|
|
|
|
'options': info.get('options', []),
|
|
|
|
|
'notes': info.get('notes', ''),
|
|
|
|
|
})
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# Try live MSF
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
|
|
|
|
msf = get_msf_interface()
|
|
|
|
|
if msf.is_connected:
|
|
|
|
|
info = msf.get_module_info(module_path)
|
|
|
|
|
if info:
|
|
|
|
|
return jsonify({
|
|
|
|
|
'path': module_path,
|
|
|
|
|
**info
|
|
|
|
|
})
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return jsonify({'error': f'Module not found: {module_path}'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/module/run', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def run_module():
|
|
|
|
|
"""Run an MSF module and stream output via SSE."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
module_path = data.get('module_path', '').strip()
|
|
|
|
|
options = data.get('options', {})
|
|
|
|
|
if not module_path:
|
|
|
|
|
return jsonify({'error': 'No module_path provided'})
|
|
|
|
|
|
|
|
|
|
job_id = str(uuid.uuid4())
|
|
|
|
|
stop_event = threading.Event()
|
|
|
|
|
_running_jobs[job_id] = stop_event
|
|
|
|
|
|
|
|
|
|
def generate():
|
|
|
|
|
yield f"data: {json.dumps({'status': 'running', 'job_id': job_id})}\n\n"
|
|
|
|
|
try:
|
|
|
|
|
from core.msf_interface import get_msf_interface
|
|
|
|
|
msf = get_msf_interface()
|
|
|
|
|
if not msf.is_connected:
|
|
|
|
|
yield f"data: {json.dumps({'error': 'Not connected to MSF'})}\n\n"
|
|
|
|
|
return
|
|
|
|
|
result = msf.run_module(module_path, options)
|
|
|
|
|
for line in (result.cleaned_output or '').splitlines():
|
|
|
|
|
if stop_event.is_set():
|
|
|
|
|
break
|
|
|
|
|
yield f"data: {json.dumps({'line': line})}\n\n"
|
|
|
|
|
yield f"data: {json.dumps({'done': True, 'findings': result.findings, 'services': result.services, 'open_ports': result.open_ports})}\n\n"
|
|
|
|
|
except Exception as e:
|
|
|
|
|
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
|
|
|
|
finally:
|
|
|
|
|
_running_jobs.pop(job_id, None)
|
|
|
|
|
|
|
|
|
|
return Response(generate(), mimetype='text/event-stream',
|
|
|
|
|
headers={'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@offense_bp.route('/module/stop', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def stop_module():
|
|
|
|
|
"""Stop a running module job."""
|
|
|
|
|
data = request.get_json(silent=True) or {}
|
|
|
|
|
job_id = data.get('job_id', '')
|
|
|
|
|
ev = _running_jobs.get(job_id)
|
|
|
|
|
if ev:
|
|
|
|
|
ev.set()
|
|
|
|
|
return jsonify({'stopped': bool(ev)})
|