An AI-augmented network reconnaissance and vulnerability triage framework, built in Python.
WireWraith combines classic host/port discovery (ARP, TCP, and Nmap-backed scanning), service fingerprinting, SMB share enumeration, NVD-backed vulnerability lookups, and an optional LLM-driven analysis layer (Gemini or a local GPT4All model) that prioritizes targets the way a human pentester would triage them during the recon phase of an engagement.
This project was built as a hands-on exercise in reproducing core nmap-style reconnaissance workflows from scratch — not as a replacement for nmap, which remains the industry-standard tool it wraps and extends in several modes here.
Legal notice. WireWraith performs active network reconnaissance (ARP sweeps, TCP connect/SYN probing, SMB enumeration, aggressive Nmap scripts). Only run it against systems and networks you own or have explicit, written authorization to test. Unauthorized scanning may be illegal in your jurisdiction. The
-ctfmode is intentionally aggressive and noisy (-p- -sV -sC -sS -T4 -Pn) and is meant strictly for lab, CTF, and authorized-assessment environments.
- Key Features
- Architecture
- Requirements
- Installation
- Configuration
- Usage
- Web Dashboard
- CLI Reference
- Example Output
- Project Structure
- Testing & CI
- Known Limitations
- Acknowledgments
- License
| Capability | Description |
|---|---|
| Host discovery | Layer 2 (ARP) and Layer 3/4 (TCP) sweeps to identify live hosts on a CIDR range, with MAC vendor lookup and TTL-based OS fingerprinting. |
| Port scanning | Multi-threaded TCP connect scanning across arbitrary port ranges. |
| Service & banner grabbing | Identifies the service running on each open port by capturing and parsing connection banners. |
| Nmap integration | Delegates host discovery, service/version detection (-sV), and full aggressive scans (-p- -sV -sC -sS) to a local Nmap installation via python-nmap. |
| SMB share enumeration | Anonymous/guest SMB share discovery and recursive file listing across all live Windows hosts, with optional bulk download of discovered files. |
| Vulnerability correlation | Matches fingerprinted service versions against the NVD CVE 2.0 API and reports CVSS-ranked results. |
| AI-assisted triage | Sends Nmap results to Gemini (cloud) or a local Llama 3 model via GPT4All (offline) to group hosts into Critical/Medium/Low priority with suggested attack vectors. |
| Rich terminal output | All results are rendered as formatted tables via rich, and AI/vulnerability findings are persisted to timestamped .txt reports. |
| Web dashboard (optional) | A read-only Streamlit dashboard (--web), styled after a spacecraft mission-control console, that visualizes hosts, ports, services, SMB shares, and CVE findings — grouped by criticality — from results already collected by the CLI. It never scans anything itself. |
flowchart LR
CLI["cli_handler.py\n(argparse)"] --> APP["main.py\nAnalyzer"]
APP --> NA["network_analyzer.py\nNetworkAnalyzer (orchestrator)"]
NA --> HS["scanners/host_scanner.py\nARP / TCP discovery"]
NA --> PS["scanners/port_scanner.py\nPort + banner scanning"]
NA --> SMB["scanners/smb_scanner.py\nSMB share enum + download"]
NA --> NM["scanners/nmap_scanner.py\nNmap host/service/CTF scans"]
NA --> VS["scanners/vulnerability_scanner.py\nNVD CVE lookup"]
NA --> AI["ai_agent.py\nAIAgent (Strategy)"]
AI --> GEM["GeminiGenerator\n(Google Gemini API)"]
AI --> GPT["GPT4AllGenerator\n(local Llama 3 GGUF)"]
VS --> NVD[("NVD CVE 2.0 API")]
APP -- "--web: writes JSON" --> STORE["web_ui/results_store.py\nmerges results per network range"]
STORE -- "reads JSON only" --> DASH["web_ui/app.py\nStreamlit dashboard (read-only)"]
NetworkAnalyzer acts as the orchestration layer: it never talks to the network directly, delegating every capability to a dedicated scanner class. The AI layer follows a Strategy pattern (AIAgent + interchangeable generators), so adding a new LLM backend only requires implementing a generate(prompt) method. The web dashboard is intentionally decoupled: main.py is the only code path that ever scans anything, results_store.py only serializes/merges results already produced by that run, and web_ui/app.py only reads that JSON file back — it never performs scanning or any other network action itself.
| Requirement | Notes |
|---|---|
| Python 3.10+ | Developed and tested on 3.13. |
| Nmap | Required and must be on PATH for -nh, -ns, and -ctf modes (python-nmap is a thin wrapper around the Nmap binary, not a reimplementation). |
| Npcap (Windows) / libpcap (Linux, macOS) | Required by Scapy for raw ARP/TCP packet crafting (--arp, --tcp). |
| Administrator / root privileges | Raw socket and ARP operations require elevated privileges on most platforms. |
| Gemini API key (optional) | Only required for -ai gemini. Get one from Google AI Studio. |
| ~5 GB free disk space (optional) | Only required for -ai gpt4all, which downloads a local Llama 3 8B Instruct GGUF model on first run. |
# 1. Clone the repository
git clone <your-repo-url>
cd WireWraith
# 2. Create and activate a virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # Linux / macOS
# 3. Install dependencies
pip install -r requirements.txt
# 4. (Optional) Configure AI credentials — see Configuration belowAlternatively, install WireWraith as an editable package to get a wirewraith console command in addition to python main.py:
pip install -e . # runtime dependencies only
pip install -e ".[dev]" # also installs pytest + ruff, see Testing & CI belowCreate a .env file in the project root to enable the cloud AI engine:
GEMINI_API_KEY=your_gemini_api_key_here| Variable | Required for | Description |
|---|---|---|
GEMINI_API_KEY |
-ai gemini |
API key used by GeminiGenerator to call the Gemini API. Not needed for -ai gpt4all, which runs fully offline. |
Run the tool as a module from the project root. All scans target a CIDR network range passed via -n/--network-range.
Discover live hosts on a local subnet (ARP sweep):
python main.py -n 192.168.1.0/24 --arpDiscover live hosts across routed networks (TCP probe, no ARP visibility required):
python main.py -n 10.0.0.0/24 --tcpScan a range of ports on all discovered hosts:
python main.py -n 192.168.1.0/24 --ports 1-1024Scan a hand-picked combination of single ports and ranges:
python main.py -n 192.168.1.0/24 --ports 21-25,80,443,3306,8080-8090Fingerprint services (banner grabbing) on open ports:
python main.py -n 192.168.1.0/24 --services 1-1024Fingerprint services and cross-reference them against known CVEs:
python main.py -n 192.168.1.0/24 --services 1-1024 -vEnumerate SMB shares and download every discovered file:
python main.py -n 192.168.1.0/24 --shared --download ./lootHost discovery delegated to Nmap:
python main.py -n 192.168.1.0/24 -nhNmap service/version detection, with AI-prioritized triage:
python main.py -n 192.168.1.0/24 -ns -ai geminiNmap service/version detection, with CVE lookup:
python main.py -n 192.168.1.0/24 -ns -vAggressive, interactive single-target scan (CTF / lab use) with local AI triage:
python main.py -n 192.168.1.0/24 -ctf -ai gpt4allVerbose troubleshooting run (full tracebacks on error):
python main.py -n 192.168.1.0/24 --services 1-1024 --debugReports from -ai and -v runs are written to the working directory as <network>_ai_report.txt and <network>_vulnerabilities_report.txt respectively.
Pass --web on any run to open a read-only, mission-control-styled Streamlit dashboard once the scan finishes:
python main.py -n 192.168.1.0/24 --services 1-1024 -v --webThe dashboard is strictly a viewer: main.py performs every scan and CVE lookup exactly as it always has, then serializes the results to .wirewraith_web/<network>.json (merging with any earlier --web runs against the same range, so hosts/ports/services/shares/vulnerabilities collected across several separate commands accumulate into one picture) and launches streamlit run web_ui/app.py to display that file. The dashboard process never scans, probes, or otherwise touches the network — it only reads JSON already written by the CLI.
It shows, depending on which scan modes were run:
- Tables for discovered hosts (IP/MAC/vendor/OS), open ports, fingerprinted services (banner-grab and/or Nmap), and SMB shares.
- Vulnerability findings grouped and color-coded by CVSS-based criticality (Critical/High/Medium/Low/Unknown), each with its CVE ID, description, affected host:port/service, and a link to the NVD entry.
- A numeric summary (hosts, open ports, services, shares, total vulnerabilities, critical+high count) and a per-severity breakdown chart.
- A sidebar with the scan history/timeline for that network range.
Because .wirewraith_web/ holds recon data about real targets, it is excluded from version control via .gitignore, same as the existing *_ai_report.txt / *_vulnerabilities_report.txt outputs.
--ports, --services, and --shared all discover live hosts internally in order to know what to scan (and --services discovers every open port before filtering down to the ones it got a banner from). Running any of these alone still fills in the dashboard's host and open-port counts from that internal discovery, even though the CLI table for that run only prints its own data type.
| Flag | Alias | Argument | Description |
|---|---|---|---|
--network-range |
-n |
CIDR (e.g. 192.168.1.0/24) |
Target network range. Required for every scan mode. |
--arp |
flag | Host discovery via ARP sweep (Layer 2, local subnet only). Mutually exclusive with --tcp. |
|
--tcp |
flag | Host discovery via TCP connect probes on ports 135/139/445. Mutually exclusive with --arp. |
|
--ports |
port spec (default: 0-65535) |
Multi-threaded TCP port scan. Accepts a single port (80), a range (21-80), or a comma-separated combination (21-25,80,8080-8090). |
|
--services |
port spec (default: 0-65535) |
Port scan plus banner grabbing to fingerprint running services. Same port spec syntax as --ports. |
|
--shared |
flag | Enumerate anonymous/guest SMB shares on discovered Windows hosts. | |
--download |
directory path (optional) | Used with --shared to bulk-download every discovered file. Defaults to ./shared. |
|
--nmap-hosts |
-nh |
flag | Host discovery delegated to Nmap (-sn). |
--nmap-services |
-ns |
flag | Service/version detection delegated to Nmap (-sV). |
--nmap-ctf |
-ctf |
flag | Interactive, aggressive single-target scan (-p- -sV -sC -sS -T4 -Pn). Lab/CTF use only. |
--ai-engine |
-ai |
gemini | gpt4all |
Enables AI-based prioritization of Nmap results. Requires -ns or -ctf. |
--vulnerabilities |
-v |
flag | Cross-references fingerprinted services against the NVD CVE database. Requires --services or -ns. |
--web |
flag | Launches the read-only Streamlit dashboard after this run finishes, visualizing whatever it collected (merged with any prior --web runs against the same network range). See Web Dashboard. |
|
--debug |
flag | Enables debug-level logging and prints full tracebacks on unhandled errors. Mutually exclusive with --quiet. |
|
--quiet |
-q |
flag | Only logs warnings and errors. Mutually exclusive with --debug. |
--arp and --tcp are enforced as mutually exclusive by argparse; combining them fails fast with a usage error. If neither host-discovery flag nor any scan mode is provided, WireWraith defaults to an ARP host scan.
Port scan followed by -v CVE correlation, from an actual run against a Metasploitable3 lab VM:
$ python main.py -n 192.168.136.142/32 --ports 21-25,80,139,445,3306,6667,6697,8080
Open Ports Scan Results
+--------------------------------------------------------------+
| IP Address | Open Ports |
|-----------------+---------------------------------------------|
| 192.168.136.142 | 21, 22, 80, 139, 445, 3306, 6667, 6697, 8080 |
+--------------------------------------------------------------+
$ python main.py -n 192.168.136.142/32 --services 21 -v
...
| CVE-2015-3306 | The mod_copy module in ProFTPD 1.3.5 allows | 10.0 | https://nvd.nist.gov/... |
| | remote attackers to read and write to | | |
| | arbitrary files via the site cpfr and site | | |
| | cpto commands. | | |
Nmap service scan piped through -ai gemini, condensed from an actual run against the same lab target (example_192.168.136.0_24_ai_report.txt):
## Target: 192.168.136.142
Attack Vector / Next Logical Step:
Begin by enumerating and attempting to exploit the outdated FTP and Samba
services, followed by the known vulnerable IRC daemon.
Known Vulnerable Services:
- ProFTPD 1.3.5 (21/ftp) -> Remote Code Execution (mod_copy)
- Samba smbd 3.X-4.X (139/netbios) -> Remote Code Execution (EternalBlue-class)
- Samba smbd 4.3.11-Ubuntu (445) -> Potential RCE if unpatched
WireWraith/
├── main.py # Entry point: CLI orchestration and mode dispatch
├── cli_handler.py # argparse definitions
├── network_analyzer.py # NetworkAnalyzer: orchestrates all scanners, renders tables
├── ai_agent.py # AIAgent + GeminiGenerator / GPT4AllGenerator (Strategy pattern)
├── requirements.txt
├── pyproject.toml # Packaging, console entry point, ruff/pytest config
├── LICENSE
├── scanners/
│ ├── __init__.py
│ ├── host_scanner.py # ARP / TCP host discovery, OS fingerprinting
│ ├── port_scanner.py # Port scanning + banner grabbing
│ ├── smb_scanner.py # SMB share enumeration and download
│ ├── nmap_scanner.py # Nmap-backed host/service/CTF scans
│ └── vulnerability_scanner.py # NVD CVE 2.0 API client
├── web_ui/
│ ├── results_store.py # Merges/persists scan results per network range to JSON
│ └── app.py # Streamlit dashboard: reads that JSON, renders it, scans nothing
├── tests/ # pytest unit tests (pure logic, no live network calls)
└── .github/workflows/ci.yml # Lint (ruff) + test (pytest) on push/PR
Unit tests cover the pure, network-free logic: port-spec parsing, banner-to-service-name extraction, CVSS parsing, and the SMB path-traversal sanitizer.
pip install -e ".[dev]"
ruff check . # lint
pytest # unit tests.github/workflows/ci.yml runs both on every push and pull request against Python 3.11 and 3.12.
These tests don't require Nmap, Npcap, or any live network access — scanning functionality itself
is validated manually against an authorized lab target (see Example Output above).
- Result reports (
*_ai_report.txt,*_vulnerabilities_report.txt), SMB downloads, and the--webdashboard's.wirewraith_web/*.jsonsession files are written to the working directory;.gitignoreexcludes them from version control, but they are not auto-cleaned between runs. - The NVD keyword search behind
-v/--webcan be noisy for generic product names (e.g. "MySQL", "UnrealIRCd"), surfacing loosely related CVEs alongside genuine matches — this is a limitation of keyword-based NVD lookups, not something the dashboard filters out. - Banner grabbing sends a generic
Hello\r\nprobe: protocols that don't respond to it (e.g. SMB on 139/445) will show as open in--portsbut won't produce a banner in--services. The--webdashboard's open-port count isn't affected by this, since it tracks discovered open ports independently of whether a banner came back. - The
-nh/-ns/-ctfmodes require a working Nmap installation onPATH; there is no pure-Python fallback.
Built on top of Scapy, python-nmap, pysmb, rich, Streamlit, the NVD CVE 2.0 API, Google Gemini, and GPT4All.
Released under the MIT License.