🔭 Oculus — Full-Spectrum Recon Orchestration

One command. 37 modules. Five concurrent phases. Asset discovery through targeted exploitation — intelligently chained, resumable, and reported.


Inspiration

Security engagements are fragmented by design — but they don't have to be.

A typical bug bounty session means subfinder in one terminal, nuclei in another, manually piping alive hosts into sqlmap, forgetting to screenshot before the session dies, and losing hours re-running what already finished. Every tool is excellent in isolation. The problem is the glue — and the total lack of visibility into what's happening across 30+ tools running simultaneously against a live target.

I built Oculus to be that glue.

One command drives the entire engagement from asset discovery to targeted exploitation — orchestrated intelligently, resumable if interrupted, with four report formats ready whether the scan finishes cleanly or gets killed halfway through.


What It Does

Oculus is a recon-to-exploitation orchestration framework for bug bounty hunters and penetration testers on Kali/Debian Linux.

It doesn't replace your tools — it chains, schedules, and reports them — through both a full CLI/TUI and a real-time web cockpit.

# Core pipeline (modules 1–8)
python3 oculus.py -d target.com --full-recon --no-confirm

# Every module, all 5 phases, set and forget
python3 oculus.py -d target.com --full-spectrum --no-confirm

# Pick modules à la carte
python3 oculus.py -d target.com --module subdomain,alive,vuln,xss,crlfuzz

# Self-update
python3 oculus.py --update

Three Automation Modes

Mode Trigger Scope Est. Time
Full Auto Recon --full-recon / [9] Core pipeline — subdomain → nuclei 15–45 min
Deep Recon --deep / [D] 14 advanced modules, picks up post-enum 1–3 hrs
Full Spectrum Scan --full-spectrum / [U] All 37 modules across 5 concurrent phases 2–6 hrs

Full Spectrum — 5-Phase Concurrent Pipeline

Phase 1 — Discovery

[Sequential]  Subdomain Enum → DNS Bruteforce → DNS Resolution → Alive Hosts → TLS Certificate Scan
[Concurrent]  ASN Mapping · Cloud Assets · OSINT · Shodan · GitHub Dorking

Phase 2 — Infrastructure

[Concurrent]  Fast Port Scan · Tech Fingerprint · WAF Detection · Screenshots · InternetDB Lookup
[Background]  Full Port Scan (Nmap) · Web Server Scan (Nikto) — run as daemon threads, joined at end

Phase 3 — Content Discovery

[Sequential]  URL Collection → Advanced Crawl (hakrawler)
[Background]  URL Crawl (Cariddi) — runs as daemon thread
[Concurrent]  Parameter Discovery · JS Endpoint + Secret Extraction
[Sequential]  Subdomain Takeover Check

Phase 4 — Vulnerability Analysis

[Sequential]  Nuclei Vulnerability Scan → GF Pattern Filters
[Background]  Jaeles Signature Scan — runs as daemon thread
[Concurrent]  Directory Fuzzing · API Route Fuzzing

Phase 5 — Targeted Exploitation

[Concurrent]  SQLi · XSS · Open Redirect · CRLF Injection · SSTI · 403 Bypass
[Concurrent]  CORS Misconfiguration · HTTP Request Smuggling
FINAL (always runs — even on Ctrl+C abort)
  show_diff → summary.txt → report.html → findings.json → report.md

37 Modules. One Framework.

# Module Tools Output
1 Subdomain Enumeration Subfinder, Amass, Assetfinder subdomains.txt
2 DNS Resolution dnsx dns_resolved.txt
3 Alive Hosts httpx + httprobe (concurrent dual-engine) alive.txt
4 Fast Port Scan Naabu / Nmap CDN fallback ports_fast.txt
5 Full Port Scan Nmap -p- -sV -sC -O (dynamic timeout scaling by host count) ports_full.txt
6 URL Collection Katana, gau, waybackurls urls_final.txt
7 WAF Detection wafw00f + WhatWaf (deep fingerprint + bypass suggestions) waf_summary.txt
8 Vulnerability Scan Nuclei nuclei/
10 Parameter Discovery ParamSpider, Arjun parameters/
11 JS Endpoints + Secrets LinkFinder + 50+ secret regex patterns js_endpoints/
12 Directory Fuzzing ffuf + nomore403 auto-feed on 403 results fuzzing/
13 API Route Fuzzing Kiterunner api_fuzzing/
14 Subdomain Takeover subzy + CNAME audit takeover/
15 Advanced Crawl hakrawler merged urls_final.txt
16 Screenshots gowitness + EyeWitness (dual-engine) screenshots/gowitness/ + screenshots/eyewitness/
17 DNS Bruteforce massdns + AlterX permutations + PureDNS wildcard filtering massdns_out.txt
18 GF Pattern Filters gf gf/ (xss, sqli, ssrf, lfi, redirect, rce)
19 Tech Fingerprint WhatWeb tech_scan/
20 SQLi sqlmap + qsreplace preprocessing sqlmap/
21 XSS Dalfox + qsreplace preprocessing xss_findings/
22 CORS Misconfiguration Python worker pool cors_findings/
23 HTTP Smuggling smuggler.py smuggling/
24 ASN / CIDR Mapping asnmap asn/
25 Cloud Asset Discovery S3 / GCS / Azure probes (open vs private differentiated) cloud/
26 GitHub Dorking GitHub Code Search API github/
27 OSINT Harvesting theHarvester osint/
28 Shodan Integration Shodan API shodan/
29 Open Redirect Python fuzzer + qsreplace preprocessing redirects/
30 Cariddi Crawl Cariddi cariddi/ (endpoints + secrets + extensions)
31 Jaeles Scan Jaeles jaeles/ (signature-based, different coverage than Nuclei)
32 SSTI Scan Tplmap (safe detection only, no RCE execution) tplmap/
33 CRLF Injection CRLFuzz crlfuzz/
34 InternetDB Lookup Shodan InternetDB API (zero-auth, no packets sent) internetdb/
35 Nikto Web Server Scan Nikto nikto/
36 TLS Certificate Scan tlsx (SANs merged back into subdomains.txt) tlsx/
37 403 Bypass nomore403 nomore403/

Key Engineering Capabilities

Capability Detail
Dual-engine alive probing httpx (JSON) and httprobe (raw) run concurrently; results merged and deduplicated — zero dropped targets
Dual-engine screenshots gowitness + EyeWitness both run per target; output segregated into separate subdirs
Non-blocking background Nmap Full port scan runs as daemon=True thread — no UI lag during slow -p- scans
Non-blocking background tools Nikto, Cariddi, and Jaeles also background-threaded; all four joined cleanly at end of pipeline
Smart DNS bruteforce chain AlterX generates permutations → massdns bruteforces → PureDNS wildcard-filters — three-stage pipeline
Dynamic resolver fallback DNS bruteforce auto-generates auto_resolvers.txt with 120+ global public resolvers if massdns resolvers file is missing
TLS SAN subdomain extraction tlsx scans CN/SAN fields across 9 ports and merges discovered subdomains back into subdomains.txt automatically
qsreplace parameter injection All parameter values replaced with FUZZ markers before SQLi, XSS, and open redirect scanning
nomore403 auto-feed After ffuf fuzzes, any 403/401 results are automatically piped into nomore403 for bypass attempts
50+ secret regex patterns JS endpoint module hunts AWS keys, GitHub tokens, JWTs, Stripe, Slack, Firebase, private keys, DB connection strings, and more
Cariddi secret merge cariddi crawl findings are cross-referenced into Module 11 secret output
crt.sh passive subdomain source Zero-install cert transparency query integrated into Module 1 alongside subfinder/amass
InternetDB passive intel Zero-auth Shodan API returns ports, CVEs, CPEs per IP — no packets sent to target
Open vs private cloud buckets Cloud module separately logs accessible [OPEN] buckets from [EXISTS/PRIVATE] ones
Module Return Status Protocol Modules return MODULE_OK / MODULE_SKIPPED / MODULE_PARTIAL / MODULE_FAILED — drives amber skip indicators in web UI
Session state + resume Every run writes session.json; resume skips steps where result key exists AND non-empty artifact is on disk
Graceful Ctrl+C abort Sets abort flag; remaining phases skipped; all four report formats still generate cleanly from partial data
Resilient HTML reporting Every HTML section wrapped in try/except — aborted scans produce clean partial reports
Thread-safe concurrency ThreadPoolExecutor + threading.Lock on shared state; per-phase scheduling with strict dependency ordering
ntfy push notifications Interactive setup wizard (--setup-ntfy) configures status-tailored push alerts (start, findings, completion, errors, skips)
Dynamic Nmap timeout scaling Full port scan timeout scales with alive host count via configurable base, per_host, and max YAML keys
Layered config DEFAULT_CONFIG~/.config/oculus/config.yaml → CLI flags; tune threads, timeouts, rate limits, wordlists, API keys
Self-update python3 oculus.py --update triggers git pull + reruns install.sh
Docker-ready Kali rolling base with full toolchain pre-installed
Single-file core Entire framework in one oculus.py — no framework overhead, drop-in portable

Real-Time Web Cockpit

The web interface wraps the native Oculus class without touching oculus.py. A thread-safe ScanEngine singleton runs scans in-process — no subprocess spawning overhead.

Architecture

Browser (React 19)
    │
    ├── REST API (FastAPI) ──── /api/scan/start · /api/scan/stop · /api/health
    │                           /api/config · /api/results/{domain}/* · /api/sessions/{domain}
    │
    └── WebSocket ─────────── ws://localhost:8000/ws/scan
                               Streams: logs + status every 500ms
                               Listens: {"action": "abort"} from client

Output Capture Pipeline

OutputCapture hooks sys.stdout at thread level
→ Strips ANSI escape codes
→ Feeds bounded queue (maxsize=50,000)
→ CLI terminal + backend logs + WebSocket all receive the same clean output

Web UI Features

🟢 Live Connection Monitor — polls /api/health every 3 seconds; pulsing neon dot reflects daemon state (ONLINE / OFFLINE) via CSS @keyframes pulse-dot

⚡ Optimization Presets — one-click execution profiles:

Preset Threads Rate Limit Timeout Jitter Severity
🐉 Kali Linux Native 100 300 240s OFF All
⚡ High Performance 200 800 300s OFF All
🥷 Stealth Operations 15 50 600s ON High + Critical

🎯 Target Scope & Limits — collapsible configurator panel lets you customize max host/URL thresholds for Arjun, ffuf, Nikto, WhatWaf, Tplmap, and nomore403 — defaulting to unlimited for full-spectrum runs

🔁 Smart Resume Detector/api/sessions/{domain} surfaces Resume Scan vs Start Fresh toggle at config time based on prior artifacts

🛑 Abort Confirmation Modal — requires explicit confirmation before dispatching termination; no accidental kills

📊 Skip-Resume Counter — when a resumed scan completes, progress bar and step counter snap to 100% regardless of skipped steps

📸 Screenshot Workspace — groups captures by inferred domain/subdomain, supports both engines, opens in near full-screen lightbox

⏩ Skipped Step Indicators — modules skipped due to missing binaries or API keys render amber fast-forward chips instead of green checks, keeping the dashboard honest

🔒 Path Traversal Protection — every artifact path is resolved and enforced to start within output-{domain}/ before serving


Multi-Format Reporting

Every run — whether it completes cleanly, resumes, or gets aborted at 40% — generates all four output formats:

Format File Contents
HTML report.html Dark theme, Chart.js visualizations, screenshot gallery, sortable findings
JSON findings.json Machine-readable structured output for downstream tooling
Markdown report.md HackerOne-style write-up, ready for submission
Summary summary.txt Human-readable plaintext overview of all 37 module results

Output Directory Structure

output-target.com/
├── session.json          # Resume state
├── summary.txt           # Quick-read scan summary
├── report.html           # Dark-themed visual report
├── findings.json         # Full structured export
├── report.md             # HackerOne-ready markdown
├── subdomains.txt        # All discovered subdomains (merged from all sources)
├── alive.txt             # Live hosts (httpx + httprobe merged)
├── dns_resolved.txt      # DNS records
├── urls_final.txt        # All collected URLs
├── ports_fast.txt / ports_full.txt
├── screenshots/
│   ├── gowitness/
│   └── eyewitness/
├── cariddi/              # Crawl findings, secrets, endpoints
├── jaeles/               # Signature vulnerability findings
├── tplmap/               # SSTI detection results
├── crlfuzz/              # CRLF injection findings
├── internetdb/           # Passive port + vuln data
├── nikto/                # Web server scan results
├── tlsx/                 # TLS SANs, cert data
├── nomore403/            # 403 bypass findings
├── gf/                   # Pattern-classified URLs
├── nuclei/               # Vulnerability scan output
├── sqlmap/ xss_findings/ cors_findings/ smuggling/ redirects/
├── parameters/ js_endpoints/ fuzzing/ api_fuzzing/ takeover/
├── asn/ cloud/ github/ osint/ shodan/ tech_scan/ waf_summary.txt
└── logs/
    ├── oculus.log
    └── errors.log

How It Was Built

Core (oculus.py, ~5,300 lines)

Single Python 3.8+ class using subprocess.Popen with streaming output, configurable timeouts, retry logic, and optional jitter. Every module method follows the same strict contract:

_require_setup() → _require_tool() → run logic → save_session()

Tool resolution searches PATH (augmented with ~/.local/bin, $GOPATH/bin, ~/go/bin), pip CLIs, /opt/recontools/ scripts, and Go binaries automatically.

Concurrency uses _run_concurrent() for parallel phase steps and _run_step() for sequential ones — both feeding the same session checkpoint with threading.Lock protecting shared state.

Background threading — Nmap, Nikto, Cariddi, and Jaeles run as daemon=True threads during their respective phases and are all joined cleanly at the end of the pipeline before reporting, so slow tools never block the scan.

Web Interface (web/)

The ScanEngine singleton instantiates Oculus directly in a background thread — no subprocess spawning. OutputCapture hooks sys.stdout, strips ANSI codes on the fly, and feeds a bounded queue.Queue(maxsize=50000). The FastAPI WebSocket endpoint polls every 500ms and streams logs + status to React 19.


Challenges

Dual-engine reconciliationhttpx outputs structured JSON; httprobe outputs raw hosts. Merging without dropping targets or introducing duplicates required format-aware parsing, not line concatenation.

37 tools, 37 exit code conventions — exit code 1 means "no results" for some tools and "crashed" for others. Consistent wrappers with tool-specific behavior took serious iteration.

Background thread progress tracking — the four background tools bypass the _run_step wrapper that feeds completed_modules. Needed a separate mechanism to append their names after join so the progress bar reaches 100%.

Resume logic correctness — detecting "already done" required two independent signals: a result key in session.json AND a non-empty artifact on disk. Either alone produced false positive skips.

tplmap false positive prevention — tplmap exits with code 0 whether or not it finds SSTI. Naive if result: would log every scanned URL as vulnerable. Fixed by parsing stdout for actual detection markers ("vulnerable", "[+]", "Engine:", "Injection:") before registering a finding.

nomore403 output preservation — naively passing the same -o file to 50 sequential nomore403 calls caused each run to overwrite the previous. Fixed by writing to unique per-URL temp files and merging.

In-process stdout capture — hooking sys.stdout at the thread level, stripping ANSI on the fly, feeding a bounded queue without blocking the scan thread, while also preserving output to the real terminal — non-trivial to get right simultaneously.


What I Learned

  • How the full attack surface lifecycle fits together — and where hunters actually lose time (it's always the wiring, not the tools)
  • Designing resumable, stateful CLI workflows with graceful abort and checkpoint recovery at scale
  • Concurrent subprocess orchestration and the race conditions that only appear when 8 tools write to the same directory simultaneously
  • Building a real-time web wrapper around an existing Python class without modifying it — thread-safe capture, WebSocket streaming, in-process execution
  • The value of resilient reporting — a scan that crashes at 80% still needs readable output
  • The gap between "tool installed" and "tool findable" across a mixed Go/pip/apt/git environment
  • Why naive exit-code-based result detection fails for tools like tplmap — and how to parse actual output markers instead

What's Next

  • 🧩 Plugin system — community-contributed modules with a standard interface
  • 🎯 Scope-aware filtering — auto-parse in-scope/out-of-scope from HackerOne and Bugcrowd program pages
  • 🔍 Cross-session report diffing — compare two scans and surface what changed
  • 📊 Interactive finding triage — severity filtering, deduplication, and tagging in the web UI
  • 🌍 ARM Docker + WSL2 — first-class support for non-Kali environments
  • ⚙️ Rate profile presets — Stealth · Balanced · Aggressive selectable at runtime without YAML edits

Built With

Python 3.8+ · FastAPI · React 19 · WebSocket · Subfinder · Amass · Nuclei · httpx · httprobe · Nmap · Naabu · sqlmap · Dalfox · ffuf · Kiterunner · gowitness · EyeWitness · massdns · PureDNS · AlterX · hakrawler · theHarvester · Cariddi · Jaeles · Tplmap · CRLFuzz · Nikto · tlsx · nomore403 · WhatWaf · qsreplace · Shodan API · GitHub API · crt.sh API · InternetDB API · Docker · Kali Linux

Built With

  • amass
  • bash
  • dalfox
  • dnsx
  • docker
  • ffuf
  • gau
  • github-api
  • go
  • gowitness
  • hakrawler
  • httpx
  • kali
  • katana
  • linux
  • massdns
  • naabu
  • nmap
  • nuclei
  • python
  • pyyaml
  • rich
  • shodan-api
  • sqlmap
  • subfinder
  • theharvester
  • wafw00f
Share this project:

Updates