Add webpage screenshot capture with Playwright
Implements automated screenshot capture for all discovered HTTP/HTTPS services using Playwright with headless Chromium. Screenshots are saved as PNG files and referenced in JSON reports. Features: - Separate ScreenshotCapture module for code organization - Viewport screenshots (1280x720) with 15-second timeout - Graceful handling of self-signed certificates - Browser reuse for optimal performance - Screenshots stored in timestamped directories - Comprehensive documentation in README.md and new CLAUDE.md Technical changes: - Added src/screenshot_capture.py: Screenshot capture module with context manager pattern - Updated src/scanner.py: Integrated screenshot capture into HTTP/HTTPS analysis phase - Updated Dockerfile: Added Chromium and Playwright browser installation - Updated requirements.txt: Added playwright==1.40.0 - Added CLAUDE.md: Developer documentation and implementation guide - Updated README.md: Enhanced features section, added screenshot details and troubleshooting - Updated .gitignore: Ignore entire output/ directory including screenshots 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ SneakyScanner - Masscan-based network scanner with YAML configuration
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
@@ -18,6 +19,8 @@ import yaml
|
||||
from libnmap.process import NmapProcess
|
||||
from libnmap.parser import NmapParser
|
||||
|
||||
from screenshot_capture import ScreenshotCapture
|
||||
|
||||
# Force unbuffered output for Docker
|
||||
sys.stdout.reconfigure(line_buffering=True)
|
||||
sys.stderr.reconfigure(line_buffering=True)
|
||||
@@ -31,6 +34,7 @@ class SneakyScanner:
|
||||
self.output_dir = Path(output_dir)
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.config = self._load_config()
|
||||
self.screenshot_capture = None
|
||||
|
||||
def _load_config(self) -> Dict[str, Any]:
|
||||
"""Load and validate YAML configuration"""
|
||||
@@ -511,6 +515,16 @@ class SneakyScanner:
|
||||
|
||||
result = {'protocol': protocol}
|
||||
|
||||
# Capture screenshot if screenshot capture is enabled
|
||||
if self.screenshot_capture:
|
||||
try:
|
||||
screenshot_path = self.screenshot_capture.capture(ip, port, protocol)
|
||||
if screenshot_path:
|
||||
result['screenshot'] = screenshot_path
|
||||
except Exception as e:
|
||||
print(f" Screenshot capture error for {ip}:{port}: {e}",
|
||||
file=sys.stderr, flush=True)
|
||||
|
||||
# If HTTPS, analyze SSL/TLS
|
||||
if protocol == 'https':
|
||||
try:
|
||||
@@ -545,6 +559,14 @@ class SneakyScanner:
|
||||
|
||||
# Record start time
|
||||
start_time = time.time()
|
||||
scan_timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
|
||||
# Initialize screenshot capture
|
||||
self.screenshot_capture = ScreenshotCapture(
|
||||
output_dir=str(self.output_dir),
|
||||
scan_timestamp=scan_timestamp,
|
||||
timeout=15
|
||||
)
|
||||
|
||||
# Collect all unique IPs
|
||||
all_ips = set()
|
||||
@@ -658,6 +680,10 @@ class SneakyScanner:
|
||||
|
||||
report['sites'].append(site_result)
|
||||
|
||||
# Clean up screenshot capture browser
|
||||
if self.screenshot_capture:
|
||||
self.screenshot_capture._close_browser()
|
||||
|
||||
return report
|
||||
|
||||
def save_report(self, report: Dict[str, Any]) -> Path:
|
||||
@@ -673,6 +699,13 @@ class SneakyScanner:
|
||||
|
||||
|
||||
def main():
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
handlers=[logging.StreamHandler(sys.stderr)]
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='SneakyScanner - Masscan-based network scanner'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user