printerxpl-forge 6.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nse/README.md +204 -0
- nse/__init__.py +6 -0
- nse/install_nse.py +412 -0
- nse/lib/printerxpl.lua +238 -0
- nse/scripts/cups-info.nse +74 -0
- nse/scripts/cups-queue-info.nse +43 -0
- nse/scripts/hp-printers-cve-2022-1026.nse +121 -0
- nse/scripts/http-device-mac.nse +107 -0
- nse/scripts/http-hp-ilo-info.nse +121 -0
- nse/scripts/http-info-xerox-enum.nse +101 -0
- nse/scripts/http-vuln-cve2022-1026.nse +158 -0
- nse/scripts/lexmark-config.nse +89 -0
- nse/scripts/pjl-ready-message.nse +106 -0
- nse/scripts/printer-banner.nse +217 -0
- nse/scripts/printer-cups-rce.nse +189 -0
- nse/scripts/printer-cve-detect.nse +279 -0
- nse/scripts/printer-discover.nse +205 -0
- nse/scripts/printer-firmware-exposed.nse +219 -0
- nse/scripts/printer-hp-pjl.nse +192 -0
- nse/scripts/printer-http-ews.nse +293 -0
- nse/scripts/printer-ipp-info.nse +235 -0
- nse/scripts/printer-lexmark-ipp.nse +203 -0
- nse/scripts/printer-passback.nse +204 -0
- nse/scripts/printer-pjl-info.nse +146 -0
- nse/scripts/printer-printnightmare.nse +211 -0
- nse/scripts/printer-snmp-info.nse +176 -0
- nse/scripts/printer-vuln-check.nse +256 -0
- nse/scripts/snmp-device-mac.nse +93 -0
- nse/scripts/snmp-info.nse +146 -0
- nse/scripts/snmp-sysdescr.nse +70 -0
- printerxpl_forge-6.2.0.dist-info/METADATA +919 -0
- printerxpl_forge-6.2.0.dist-info/RECORD +97 -0
- printerxpl_forge-6.2.0.dist-info/WHEEL +5 -0
- printerxpl_forge-6.2.0.dist-info/entry_points.txt +4 -0
- printerxpl_forge-6.2.0.dist-info/licenses/LICENSE +21 -0
- printerxpl_forge-6.2.0.dist-info/top_level.txt +4 -0
- src/assets/fonts/gunplay.pfa +1671 -0
- src/assets/fonts/kshandwrt.pfa +315 -0
- src/assets/fonts/laksoner.pfa +2402 -0
- src/assets/fonts/paintcans.pfa +9699 -0
- src/assets/fonts/stencilod.pfa +4076 -0
- src/assets/fonts/takecover.pfa +26138 -0
- src/assets/fonts/topsecret.pfa +6652 -0
- src/assets/fonts/whoa.pfa +773 -0
- src/assets/mibs/HOST-RESOURCES-MIB +1540 -0
- src/assets/mibs/Printer-MIB +4389 -0
- src/assets/mibs/README.md +9 -0
- src/assets/mibs/SNMPv2-MIB +854 -0
- src/assets/overlays/hacker.eps +596 -0
- src/assets/overlays/smiley.eps +214 -0
- src/assets/overlays/smiley2.eps +240 -0
- src/core/attack_orchestrator.py +1025 -0
- src/core/capabilities.py +323 -0
- src/core/destructive_audit.py +430 -0
- src/core/discovery.py +488 -0
- src/core/osdetect.py +74 -0
- src/core/poly_runner.py +579 -0
- src/core/printer.py +1426 -0
- src/main.py +2134 -0
- src/modules/install_printer.py +318 -0
- src/modules/login_bruteforce.py +852 -0
- src/modules/pcl.py +506 -0
- src/modules/pjl.py +3575 -0
- src/modules/print_job.py +1290 -0
- src/modules/ps.py +1102 -0
- src/payloads/__init__.py +98 -0
- src/payloads/assets/overlays/notice.eps +9 -0
- src/protocols/__init__.py +19 -0
- src/protocols/firmware.py +738 -0
- src/protocols/ipp.py +216 -0
- src/protocols/ipp_attacks.py +609 -0
- src/protocols/lpd.py +141 -0
- src/protocols/network_map.py +1004 -0
- src/protocols/raw.py +173 -0
- src/protocols/smb.py +359 -0
- src/protocols/ssrf_pivot.py +427 -0
- src/protocols/storage.py +587 -0
- src/ui/__init__.py +6 -0
- src/ui/interactive.py +742 -0
- src/ui/spinner.py +112 -0
- src/ui/tables.py +132 -0
- src/utils/banner_grabber.py +852 -0
- src/utils/codebook.py +456 -0
- src/utils/config.py +522 -0
- src/utils/cve_loader.py +158 -0
- src/utils/default_creds.py +134 -0
- src/utils/discovery_online.py +1327 -0
- src/utils/exploit_manager.py +805 -0
- src/utils/fuzzer.py +220 -0
- src/utils/helper.py +732 -0
- src/utils/local_printers.py +307 -0
- src/utils/ml_engine.py +491 -0
- src/utils/operators.py +474 -0
- src/utils/ports.py +234 -0
- src/utils/vuln_scanner.py +823 -0
- src/utils/wordlist_loader.py +412 -0
- src/version.py +36 -0
nse/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# PrinterXPL-Forge — Nmap NSE Scripts
|
|
2
|
+
|
|
3
|
+
> Author: André Henrique (@mrhenrike) | União Geek
|
|
4
|
+
> Repo: https://github.com/mrhenrike/PrinterXPL-Forge
|
|
5
|
+
> Docs: https://github.com/mrhenrike/PrinterXPL-Forge/wiki/NSE
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
12 Nmap Scripting Engine (NSE) scripts + 1 shared Lua library for **printer and MFP security assessment**.
|
|
12
|
+
|
|
13
|
+
These scripts complement the full PrinterXPL-Forge toolkit, providing:
|
|
14
|
+
- Multi-protocol banner grabbing and vendor fingerprinting
|
|
15
|
+
- CVE cross-reference against 80+ printer vulnerabilities
|
|
16
|
+
- Lightweight active probes (non-destructive)
|
|
17
|
+
- LDAP/SMB passback attack surface detection
|
|
18
|
+
- Firmware update endpoint exposure detection
|
|
19
|
+
- Exploit module suggestions for full exploitation
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Quick Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 1. Install PrinterXPL-Forge with NSE extras
|
|
27
|
+
pip install printerxpl-forge[nse]
|
|
28
|
+
|
|
29
|
+
# 2. Deploy scripts to Nmap (requires elevated privileges)
|
|
30
|
+
printerxpl-nse install
|
|
31
|
+
|
|
32
|
+
# 3. Verify
|
|
33
|
+
printerxpl-nse status
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
On Windows (Administrator PowerShell):
|
|
37
|
+
```powershell
|
|
38
|
+
pip install printerxpl-forge[nse]
|
|
39
|
+
printerxpl-nse install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## NSE Scripts
|
|
45
|
+
|
|
46
|
+
| Script | Ports | Description |
|
|
47
|
+
|--------|-------|-------------|
|
|
48
|
+
| `printer-discover.nse` | 9100, 631, 80, 443, 515, 23 | Fast multi-protocol printer discovery |
|
|
49
|
+
| `printer-banner.nse` | 9100, 631, 80, 443, 515 | Full banner grab + vendor fingerprint |
|
|
50
|
+
| `printer-pjl-info.nse` | 9100 | Deep PJL enumeration (NVRAM, FS, vars) |
|
|
51
|
+
| `printer-ipp-info.nse` | 631 | IPP Get-Printer-Attributes + CVE check |
|
|
52
|
+
| `printer-http-ews.nse` | 80, 443 | HTTP EWS fingerprint + default creds |
|
|
53
|
+
| `printer-snmp-info.nse` | 161/udp | SNMP Printer MIB enumeration |
|
|
54
|
+
| `printer-cve-detect.nse` | Any | CVE cross-reference (80+ CVEs, 15 vendors) |
|
|
55
|
+
| `printer-vuln-check.nse` | Any | Active non-destructive vuln validation |
|
|
56
|
+
| `printer-cups-rce.nse` | 631 | CUPS CVE-2024-47176 / CVE-2026-34980 |
|
|
57
|
+
| `printer-hp-pjl.nse` | 9100 | HP-specific PJL deep scan + CVE check |
|
|
58
|
+
| `printer-firmware-exposed.nse` | 80, 443 | Firmware update endpoint detection |
|
|
59
|
+
| `printer-passback.nse` | 80, 443 | LDAP/SMB passback attack surface |
|
|
60
|
+
| `printer-lexmark-ipp.nse` | 631, 80 | Lexmark-specific IPP + EWS CVE check |
|
|
61
|
+
| `printer-printnightmare.nse` | 445, 135 | Windows Print Spooler family check |
|
|
62
|
+
|
|
63
|
+
**Shared library:** `lib/printerxpl.lua` — vendor patterns, CVE DB, verdict formatting
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Usage Examples
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Discovery across a subnet
|
|
71
|
+
nmap -sV --open -p 9100,631,80 --script printer-discover 192.168.1.0/24
|
|
72
|
+
|
|
73
|
+
# Full assessment on a single target
|
|
74
|
+
nmap -p 9100,631,80,443,427,515 --script 'printer-*' <target>
|
|
75
|
+
|
|
76
|
+
# HP-specific deep scan
|
|
77
|
+
nmap -p 9100 --script printer-hp-pjl <target>
|
|
78
|
+
|
|
79
|
+
# CUPS RCE check (CVE-2026-34980)
|
|
80
|
+
nmap -p 631 --script printer-cups-rce <target>
|
|
81
|
+
|
|
82
|
+
# CVE cross-reference only (safe, no active probes)
|
|
83
|
+
nmap -p 9100,631,80 --script printer-banner,printer-cve-detect <target>
|
|
84
|
+
|
|
85
|
+
# LDAP/SMB passback surface
|
|
86
|
+
nmap -p 80,443 --script printer-passback <target>
|
|
87
|
+
|
|
88
|
+
# Firmware endpoint exposure
|
|
89
|
+
nmap -p 80,443 --script printer-firmware-exposed <target>
|
|
90
|
+
|
|
91
|
+
# Windows Print Spooler (PrintNightmare family)
|
|
92
|
+
nmap -p 445,135 --script printer-printnightmare <target>
|
|
93
|
+
|
|
94
|
+
# SNMP printer MIB dump
|
|
95
|
+
nmap -sU -p 161 --script printer-snmp-info <target>
|
|
96
|
+
|
|
97
|
+
# Active vulnerability validation (intrusive)
|
|
98
|
+
nmap -p 9100,631,80,427,445 --script printer-vuln-check <target>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Verdict System
|
|
104
|
+
|
|
105
|
+
Each script returns one of:
|
|
106
|
+
|
|
107
|
+
| Verdict | Meaning |
|
|
108
|
+
|---------|---------|
|
|
109
|
+
| `VULNERABLE` | Active probe confirmed the vulnerability |
|
|
110
|
+
| `POSSIBLY VULNERABLE` | CVE match or passive indicator — confirm with printer-vuln-check |
|
|
111
|
+
| `NOT VULNERABLE` | No CVE match / active probe ruled out |
|
|
112
|
+
| `UNKNOWN` | Insufficient data — combine with other scripts |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## CVE Coverage (selected)
|
|
117
|
+
|
|
118
|
+
| CVE | CVSS | Vendor | Description |
|
|
119
|
+
|-----|------|--------|-------------|
|
|
120
|
+
| CVE-2026-34980 | 9.1 | CUPS | Unauthenticated RCE via PPD injection |
|
|
121
|
+
| CVE-2025-26506 | 9.8 | HP | LaserJet Enterprise PostScript RCE |
|
|
122
|
+
| CVE-2024-47176 | 9.9 | CUPS | cups-browsed unauthenticated RCE chain |
|
|
123
|
+
| CVE-2023-23560 | 9.0 | Lexmark | SSRF-to-RCE (Pwn2Own Toronto 2022) |
|
|
124
|
+
| CVE-2022-24673 | 9.8 | Canon | SLP pre-auth stack buffer overflow RCE |
|
|
125
|
+
| CVE-2022-45796 | 9.8 | Sharp | Unauthenticated OS command injection |
|
|
126
|
+
| CVE-2021-1675 | 9.8 | Microsoft | PrintNightmare — Windows Spooler RCE |
|
|
127
|
+
| CVE-2022-38028 | 7.8 | Microsoft | GooseEgg — APT28 Spooler LPE (KEV) |
|
|
128
|
+
| CVE-2017-2741 | 9.8 | HP | PJL path traversal to RCE |
|
|
129
|
+
|
|
130
|
+
Full CVE list: `src/data/cve_catalog.json` (80+ entries)
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Full Exploitation
|
|
135
|
+
|
|
136
|
+
When Nmap suggests a module, run the full exploit with PrinterXPL-Forge:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pip install printerxpl-forge
|
|
140
|
+
|
|
141
|
+
# Scan all ports
|
|
142
|
+
printerxpl-forge scan --target <IP>
|
|
143
|
+
|
|
144
|
+
# Run specific module (dry-run first)
|
|
145
|
+
printerxpl-forge run --module xpl/edb-cve-2025-26506 --dry-run --target <IP>
|
|
146
|
+
printerxpl-forge run --module xpl/edb-cve-2025-26506 --target <IP>
|
|
147
|
+
|
|
148
|
+
# Check without exploiting
|
|
149
|
+
printerxpl-forge check --module xpl/edb-cve-2025-26506 --target <IP>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## CLI Reference
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
printerxpl-nse <command> [options]
|
|
158
|
+
|
|
159
|
+
Commands:
|
|
160
|
+
install Copy NSE scripts to Nmap scripts directory
|
|
161
|
+
uninstall Remove NSE scripts from Nmap
|
|
162
|
+
list List all bundled scripts
|
|
163
|
+
status Check installation status
|
|
164
|
+
path Show detected Nmap directories
|
|
165
|
+
verify Verify scripts load in Nmap
|
|
166
|
+
|
|
167
|
+
Options (install/uninstall):
|
|
168
|
+
--scripts-dir PATH Override Nmap scripts directory
|
|
169
|
+
--nselib-dir PATH Override Nmap nselib directory (for shared lib)
|
|
170
|
+
--no-db-update Skip nmap --script-updatedb after install
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## File Structure
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
nse/
|
|
179
|
+
├── __init__.py
|
|
180
|
+
├── install_nse.py ← CLI installer (printerxpl-nse)
|
|
181
|
+
├── README.md
|
|
182
|
+
├── scripts/
|
|
183
|
+
│ ├── printer-banner.nse
|
|
184
|
+
│ ├── printer-pjl-info.nse
|
|
185
|
+
│ ├── printer-ipp-info.nse
|
|
186
|
+
│ ├── printer-http-ews.nse
|
|
187
|
+
│ ├── printer-snmp-info.nse
|
|
188
|
+
│ ├── printer-cve-detect.nse
|
|
189
|
+
│ ├── printer-vuln-check.nse
|
|
190
|
+
│ ├── printer-cups-rce.nse
|
|
191
|
+
│ ├── printer-hp-pjl.nse
|
|
192
|
+
│ ├── printer-firmware-exposed.nse
|
|
193
|
+
│ ├── printer-passback.nse
|
|
194
|
+
│ ├── printer-lexmark-ipp.nse
|
|
195
|
+
│ ├── printer-printnightmare.nse
|
|
196
|
+
│ └── printer-discover.nse
|
|
197
|
+
└── lib/
|
|
198
|
+
└── printerxpl.lua ← Shared Lua library
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
> Created by André Henrique (@mrhenrike) — União Geek
|
|
204
|
+
> https://github.com/Uniao-Geek
|
nse/__init__.py
ADDED
nse/install_nse.py
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
printerxpl-nse — NSE Script Installer for PrinterXPL-Forge
|
|
5
|
+
===========================================================
|
|
6
|
+
Copies PrinterXPL-Forge Nmap NSE scripts and the shared printerxpl.lua library
|
|
7
|
+
into the active Nmap script directory so they become available system-wide.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
printerxpl-nse install # install scripts
|
|
11
|
+
printerxpl-nse uninstall # remove scripts
|
|
12
|
+
printerxpl-nse list # list installed scripts
|
|
13
|
+
printerxpl-nse status # check installation status
|
|
14
|
+
printerxpl-nse path # show detected nmap scripts dir
|
|
15
|
+
printerxpl-nse verify # verify nmap can load the scripts
|
|
16
|
+
|
|
17
|
+
Author: André Henrique (@mrhenrike) | União Geek
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import os
|
|
24
|
+
import platform
|
|
25
|
+
import shutil
|
|
26
|
+
import subprocess
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
# ── Package layout ────────────────────────────────────────────────────────────
|
|
31
|
+
_THIS_DIR = Path(__file__).parent.resolve()
|
|
32
|
+
_SCRIPTS_DIR = _THIS_DIR / "scripts"
|
|
33
|
+
_LIB_DIR = _THIS_DIR / "lib"
|
|
34
|
+
|
|
35
|
+
NSE_SCRIPTS = sorted(_SCRIPTS_DIR.glob("*.nse"))
|
|
36
|
+
NSE_LIBS = sorted(_LIB_DIR.glob("*.lua"))
|
|
37
|
+
ALL_NSE = NSE_SCRIPTS + NSE_LIBS
|
|
38
|
+
|
|
39
|
+
SCRIPT_NAMES = [f.name for f in NSE_SCRIPTS]
|
|
40
|
+
LIB_NAMES = [f.name for f in NSE_LIBS]
|
|
41
|
+
|
|
42
|
+
BANNER = r"""
|
|
43
|
+
____ _ _ __ ______ _
|
|
44
|
+
| _ \ _ __(_)_ __ | |_ ___ _ __ \ \/ / _ \| |
|
|
45
|
+
| |_) | '__| | '_ \| __/ _ \ '__| > <| |_) | |
|
|
46
|
+
| __/| | | | | | | || __/ | / /\ \ __/| |___
|
|
47
|
+
|_| |_| |_|_| |_|\__\___|_| /_/ \_\_| |_____| NSE Installer v5.0.0
|
|
48
|
+
|
|
49
|
+
André Henrique (@mrhenrike) | União Geek
|
|
50
|
+
https://github.com/mrhenrike/PrinterXPL-Forge
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ── Nmap detection ────────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
def _find_nmap() -> tuple[str | None, Path | None]:
|
|
57
|
+
"""Return (nmap_binary_path, nmap_scripts_dir)."""
|
|
58
|
+
nmap_bin = shutil.which("nmap")
|
|
59
|
+
if not nmap_bin:
|
|
60
|
+
return None, None
|
|
61
|
+
|
|
62
|
+
# Ask nmap where its datadir is
|
|
63
|
+
try:
|
|
64
|
+
result = subprocess.run(
|
|
65
|
+
[nmap_bin, "--version"],
|
|
66
|
+
capture_output=True, text=True, timeout=10,
|
|
67
|
+
)
|
|
68
|
+
output = result.stdout + result.stderr
|
|
69
|
+
except Exception:
|
|
70
|
+
output = ""
|
|
71
|
+
|
|
72
|
+
# Common platform paths
|
|
73
|
+
candidates: list[Path] = []
|
|
74
|
+
system = platform.system()
|
|
75
|
+
|
|
76
|
+
if system == "Windows":
|
|
77
|
+
candidates += [
|
|
78
|
+
Path(r"C:\Program Files (x86)\Nmap\scripts"),
|
|
79
|
+
Path(r"C:\Program Files\Nmap\scripts"),
|
|
80
|
+
]
|
|
81
|
+
nmap_dir = Path(nmap_bin).parent if nmap_bin else None
|
|
82
|
+
if nmap_dir:
|
|
83
|
+
candidates.insert(0, nmap_dir / "scripts")
|
|
84
|
+
|
|
85
|
+
elif system == "Darwin":
|
|
86
|
+
candidates += [
|
|
87
|
+
Path("/usr/local/share/nmap/scripts"),
|
|
88
|
+
Path("/opt/homebrew/share/nmap/scripts"),
|
|
89
|
+
Path("/usr/share/nmap/scripts"),
|
|
90
|
+
]
|
|
91
|
+
else: # Linux
|
|
92
|
+
candidates += [
|
|
93
|
+
Path("/usr/share/nmap/scripts"),
|
|
94
|
+
Path("/usr/local/share/nmap/scripts"),
|
|
95
|
+
Path("/opt/nmap/share/nmap/scripts"),
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
for c in candidates:
|
|
99
|
+
if c.is_dir():
|
|
100
|
+
return nmap_bin, c
|
|
101
|
+
|
|
102
|
+
return nmap_bin, None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _find_nmap_nselib() -> Path | None:
|
|
106
|
+
"""Find the nmap nselib directory for shared libraries."""
|
|
107
|
+
_, scripts_dir = _find_nmap()
|
|
108
|
+
if scripts_dir is None:
|
|
109
|
+
return None
|
|
110
|
+
# nselib is typically sibling of scripts
|
|
111
|
+
nselib = scripts_dir.parent / "nselib"
|
|
112
|
+
if nselib.is_dir():
|
|
113
|
+
return nselib
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# ── Install / uninstall ───────────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
def cmd_install(args: argparse.Namespace) -> int:
|
|
120
|
+
print(BANNER)
|
|
121
|
+
nmap_bin, scripts_dir = _find_nmap()
|
|
122
|
+
|
|
123
|
+
if not nmap_bin:
|
|
124
|
+
print("[ERROR] Nmap not found in PATH. Install nmap first:")
|
|
125
|
+
print(" https://nmap.org/download.html")
|
|
126
|
+
return 1
|
|
127
|
+
|
|
128
|
+
print(f"[INFO] Nmap binary : {nmap_bin}")
|
|
129
|
+
|
|
130
|
+
if scripts_dir is None:
|
|
131
|
+
if args.scripts_dir:
|
|
132
|
+
scripts_dir = Path(args.scripts_dir)
|
|
133
|
+
else:
|
|
134
|
+
print("[ERROR] Nmap scripts directory not found automatically.")
|
|
135
|
+
print(" Use: printerxpl-nse install --scripts-dir /path/to/nmap/scripts")
|
|
136
|
+
return 1
|
|
137
|
+
|
|
138
|
+
print(f"[INFO] Scripts dir : {scripts_dir}")
|
|
139
|
+
|
|
140
|
+
# NSE lib dir
|
|
141
|
+
nselib_dir = _find_nmap_nselib()
|
|
142
|
+
if nselib_dir is None and args.nselib_dir:
|
|
143
|
+
nselib_dir = Path(args.nselib_dir)
|
|
144
|
+
|
|
145
|
+
# Copy scripts
|
|
146
|
+
installed = []
|
|
147
|
+
errors = []
|
|
148
|
+
|
|
149
|
+
for src in NSE_SCRIPTS:
|
|
150
|
+
dst = scripts_dir / src.name
|
|
151
|
+
try:
|
|
152
|
+
shutil.copy2(src, dst)
|
|
153
|
+
print(f"[+] Installed {src.name} → {dst}")
|
|
154
|
+
installed.append(src.name)
|
|
155
|
+
except PermissionError:
|
|
156
|
+
print(f"[!] Permission denied: {dst}")
|
|
157
|
+
print(f" Retry with sudo / Administrator privileges")
|
|
158
|
+
errors.append(src.name)
|
|
159
|
+
except Exception as exc:
|
|
160
|
+
print(f"[!] Failed to copy {src.name}: {exc}")
|
|
161
|
+
errors.append(src.name)
|
|
162
|
+
|
|
163
|
+
# Copy shared library (printerxpl.lua)
|
|
164
|
+
for lib in NSE_LIBS:
|
|
165
|
+
# Try nselib first, fall back to scripts dir
|
|
166
|
+
lib_target_dir = nselib_dir or scripts_dir
|
|
167
|
+
dst = lib_target_dir / lib.name
|
|
168
|
+
try:
|
|
169
|
+
shutil.copy2(lib, dst)
|
|
170
|
+
print(f"[+] Installed {lib.name} → {dst}")
|
|
171
|
+
installed.append(lib.name)
|
|
172
|
+
except PermissionError:
|
|
173
|
+
print(f"[!] Permission denied: {dst}")
|
|
174
|
+
errors.append(lib.name)
|
|
175
|
+
except Exception as exc:
|
|
176
|
+
print(f"[!] Failed to copy {lib.name}: {exc}")
|
|
177
|
+
errors.append(lib.name)
|
|
178
|
+
|
|
179
|
+
# Update nmap script database
|
|
180
|
+
if installed and not args.no_db_update:
|
|
181
|
+
print("[INFO] Updating nmap script database (nmap --script-updatedb)…")
|
|
182
|
+
try:
|
|
183
|
+
subprocess.run([nmap_bin, "--script-updatedb"],
|
|
184
|
+
timeout=30, check=False)
|
|
185
|
+
except Exception as exc:
|
|
186
|
+
print(f"[WARN] --script-updatedb failed: {exc}")
|
|
187
|
+
|
|
188
|
+
print()
|
|
189
|
+
if errors:
|
|
190
|
+
print(f"[WARN] {len(errors)} file(s) failed — re-run with elevated privileges")
|
|
191
|
+
print(f"[OK] {len(installed)} file(s) installed successfully")
|
|
192
|
+
return 1
|
|
193
|
+
else:
|
|
194
|
+
print(f"[OK] {len(installed)} NSE files installed successfully")
|
|
195
|
+
_print_usage_hint()
|
|
196
|
+
return 0
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def cmd_uninstall(args: argparse.Namespace) -> int:
|
|
200
|
+
print(BANNER)
|
|
201
|
+
_, scripts_dir = _find_nmap()
|
|
202
|
+
if scripts_dir is None and not args.scripts_dir:
|
|
203
|
+
print("[ERROR] Nmap scripts directory not found. Use --scripts-dir")
|
|
204
|
+
return 1
|
|
205
|
+
if args.scripts_dir:
|
|
206
|
+
scripts_dir = Path(args.scripts_dir)
|
|
207
|
+
|
|
208
|
+
nselib_dir = _find_nmap_nselib()
|
|
209
|
+
|
|
210
|
+
removed = 0
|
|
211
|
+
for name in SCRIPT_NAMES:
|
|
212
|
+
target = scripts_dir / name
|
|
213
|
+
if target.exists():
|
|
214
|
+
try:
|
|
215
|
+
target.unlink()
|
|
216
|
+
print(f"[-] Removed {target}")
|
|
217
|
+
removed += 1
|
|
218
|
+
except Exception as exc:
|
|
219
|
+
print(f"[!] Could not remove {target}: {exc}")
|
|
220
|
+
|
|
221
|
+
for name in LIB_NAMES:
|
|
222
|
+
for search_dir in [nselib_dir, scripts_dir]:
|
|
223
|
+
if search_dir is None:
|
|
224
|
+
continue
|
|
225
|
+
target = search_dir / name
|
|
226
|
+
if target.exists():
|
|
227
|
+
try:
|
|
228
|
+
target.unlink()
|
|
229
|
+
print(f"[-] Removed {target}")
|
|
230
|
+
removed += 1
|
|
231
|
+
except Exception as exc:
|
|
232
|
+
print(f"[!] Could not remove {target}: {exc}")
|
|
233
|
+
|
|
234
|
+
print(f"\n[OK] {removed} file(s) removed")
|
|
235
|
+
return 0
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def cmd_list(_: argparse.Namespace) -> int:
|
|
239
|
+
print(BANNER)
|
|
240
|
+
print(f"PrinterXPL-Forge NSE Bundle ({len(NSE_SCRIPTS)} scripts + {len(NSE_LIBS)} libs)\n")
|
|
241
|
+
print("Scripts:")
|
|
242
|
+
for s in NSE_SCRIPTS:
|
|
243
|
+
# Extract first @usage line for description
|
|
244
|
+
try:
|
|
245
|
+
lines = s.read_text(encoding="utf-8", errors="replace").splitlines()
|
|
246
|
+
desc = next((l.strip().lstrip("-").strip() for l in lines if l.strip().startswith("--") and len(l) > 10), "")
|
|
247
|
+
except Exception:
|
|
248
|
+
desc = ""
|
|
249
|
+
print(f" {s.stem:<35} {desc[:60]}")
|
|
250
|
+
print()
|
|
251
|
+
print("Shared Libraries:")
|
|
252
|
+
for lib in NSE_LIBS:
|
|
253
|
+
print(f" {lib.name}")
|
|
254
|
+
return 0
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def cmd_status(_: argparse.Namespace) -> int:
|
|
258
|
+
_, scripts_dir = _find_nmap()
|
|
259
|
+
nmap_bin, _ = _find_nmap()
|
|
260
|
+
|
|
261
|
+
print(f"Nmap binary : {nmap_bin or 'NOT FOUND'}")
|
|
262
|
+
print(f"Scripts dir : {scripts_dir or 'NOT FOUND'}")
|
|
263
|
+
print()
|
|
264
|
+
|
|
265
|
+
if scripts_dir is None:
|
|
266
|
+
print("[NOT INSTALLED] nmap scripts directory not found")
|
|
267
|
+
return 1
|
|
268
|
+
|
|
269
|
+
ok = 0; missing = 0
|
|
270
|
+
for name in SCRIPT_NAMES + LIB_NAMES:
|
|
271
|
+
target = scripts_dir / name
|
|
272
|
+
if target.exists():
|
|
273
|
+
print(f" [OK] {name}")
|
|
274
|
+
ok += 1
|
|
275
|
+
else:
|
|
276
|
+
print(f" [MISSING] {name}")
|
|
277
|
+
missing += 1
|
|
278
|
+
|
|
279
|
+
print()
|
|
280
|
+
if missing == 0:
|
|
281
|
+
print(f"[INSTALLED] All {ok} files present in {scripts_dir}")
|
|
282
|
+
_print_usage_hint()
|
|
283
|
+
return 0
|
|
284
|
+
elif ok == 0:
|
|
285
|
+
print("[NOT INSTALLED] No files installed yet — run: printerxpl-nse install")
|
|
286
|
+
return 1
|
|
287
|
+
else:
|
|
288
|
+
print(f"[PARTIAL] {ok} installed, {missing} missing — re-run install")
|
|
289
|
+
return 1
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def cmd_path(_: argparse.Namespace) -> int:
|
|
293
|
+
nmap_bin, scripts_dir = _find_nmap()
|
|
294
|
+
print(f"Nmap binary : {nmap_bin or 'not found'}")
|
|
295
|
+
print(f"Scripts dir : {scripts_dir or 'not found'}")
|
|
296
|
+
nselib = _find_nmap_nselib()
|
|
297
|
+
print(f"NSElib dir : {nselib or 'not found'}")
|
|
298
|
+
return 0
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def cmd_verify(_: argparse.Namespace) -> int:
|
|
302
|
+
nmap_bin, scripts_dir = _find_nmap()
|
|
303
|
+
if not nmap_bin:
|
|
304
|
+
print("[ERROR] Nmap not found"); return 1
|
|
305
|
+
if scripts_dir is None:
|
|
306
|
+
print("[ERROR] Scripts dir not found"); return 1
|
|
307
|
+
|
|
308
|
+
print("Verifying NSE scripts with nmap --script-help…\n")
|
|
309
|
+
errors = 0
|
|
310
|
+
for name in SCRIPT_NAMES:
|
|
311
|
+
target = scripts_dir / name
|
|
312
|
+
if not target.exists():
|
|
313
|
+
print(f" [MISSING] {name}")
|
|
314
|
+
errors += 1
|
|
315
|
+
continue
|
|
316
|
+
try:
|
|
317
|
+
result = subprocess.run(
|
|
318
|
+
[nmap_bin, "--script-help", name.replace(".nse", "")],
|
|
319
|
+
capture_output=True, text=True, timeout=10,
|
|
320
|
+
)
|
|
321
|
+
if result.returncode == 0:
|
|
322
|
+
print(f" [OK] {name}")
|
|
323
|
+
else:
|
|
324
|
+
print(f" [FAIL] {name} — {result.stderr.strip()[:80]}")
|
|
325
|
+
errors += 1
|
|
326
|
+
except Exception as exc:
|
|
327
|
+
print(f" [ERROR] {name} — {exc}")
|
|
328
|
+
errors += 1
|
|
329
|
+
|
|
330
|
+
print()
|
|
331
|
+
if errors:
|
|
332
|
+
print(f"[WARN] {errors} script(s) failed verification")
|
|
333
|
+
return 1
|
|
334
|
+
print(f"[OK] All {len(SCRIPT_NAMES)} scripts verified")
|
|
335
|
+
return 0
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _print_usage_hint() -> None:
|
|
339
|
+
print()
|
|
340
|
+
print("=" * 68)
|
|
341
|
+
print(" PrinterXPL-Forge NSE scripts are now available in Nmap!")
|
|
342
|
+
print()
|
|
343
|
+
print(" Quick discovery:")
|
|
344
|
+
print(" nmap -p 9100,631,80 --script printer-discover <target>")
|
|
345
|
+
print()
|
|
346
|
+
print(" Full scan (all scripts):")
|
|
347
|
+
print(" nmap -p 9100,631,80,443,427,515 \\")
|
|
348
|
+
print(" --script 'printer-*' <target>")
|
|
349
|
+
print()
|
|
350
|
+
print(" Targeted checks:")
|
|
351
|
+
print(" nmap -p 9100 --script printer-hp-pjl <target>")
|
|
352
|
+
print(" nmap -p 631 --script printer-cups-rce <target>")
|
|
353
|
+
print(" nmap -p 9100,631,80 --script printer-cve-detect <target>")
|
|
354
|
+
print(" nmap -p 80,443 --script printer-passback <target>")
|
|
355
|
+
print(" nmap -p 445 --script printer-printnightmare <target>")
|
|
356
|
+
print()
|
|
357
|
+
print(" Full exploitation:")
|
|
358
|
+
print(" pip install printerxpl-forge")
|
|
359
|
+
print(" printerxpl-forge scan --target <IP>")
|
|
360
|
+
print("=" * 68)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# ── Entry point ───────────────────────────────────────────────────────────────
|
|
364
|
+
|
|
365
|
+
def main(argv: list[str] | None = None) -> int:
|
|
366
|
+
parser = argparse.ArgumentParser(
|
|
367
|
+
prog="printerxpl-nse",
|
|
368
|
+
description="PrinterXPL-Forge — Nmap NSE script installer",
|
|
369
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
370
|
+
)
|
|
371
|
+
sub = parser.add_subparsers(dest="cmd", metavar="COMMAND")
|
|
372
|
+
|
|
373
|
+
# install
|
|
374
|
+
p_install = sub.add_parser("install", help="Install NSE scripts to Nmap")
|
|
375
|
+
p_install.add_argument("--scripts-dir", metavar="PATH",
|
|
376
|
+
help="Override Nmap scripts directory")
|
|
377
|
+
p_install.add_argument("--nselib-dir", metavar="PATH",
|
|
378
|
+
help="Override Nmap nselib directory (for printerxpl.lua)")
|
|
379
|
+
p_install.add_argument("--no-db-update", action="store_true",
|
|
380
|
+
help="Skip nmap --script-updatedb after install")
|
|
381
|
+
|
|
382
|
+
# uninstall
|
|
383
|
+
p_uninstall = sub.add_parser("uninstall", help="Remove NSE scripts from Nmap")
|
|
384
|
+
p_uninstall.add_argument("--scripts-dir", metavar="PATH",
|
|
385
|
+
help="Override Nmap scripts directory")
|
|
386
|
+
|
|
387
|
+
# list / status / path / verify
|
|
388
|
+
sub.add_parser("list", help="List all NSE scripts in this bundle")
|
|
389
|
+
sub.add_parser("status", help="Check installation status")
|
|
390
|
+
sub.add_parser("path", help="Show detected Nmap directories")
|
|
391
|
+
sub.add_parser("verify", help="Verify scripts load correctly in Nmap")
|
|
392
|
+
|
|
393
|
+
args = parser.parse_args(argv)
|
|
394
|
+
|
|
395
|
+
dispatch = {
|
|
396
|
+
"install": cmd_install,
|
|
397
|
+
"uninstall": cmd_uninstall,
|
|
398
|
+
"list": cmd_list,
|
|
399
|
+
"status": cmd_status,
|
|
400
|
+
"path": cmd_path,
|
|
401
|
+
"verify": cmd_verify,
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if args.cmd in dispatch:
|
|
405
|
+
return dispatch[args.cmd](args)
|
|
406
|
+
|
|
407
|
+
parser.print_help()
|
|
408
|
+
return 0
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
if __name__ == "__main__":
|
|
412
|
+
sys.exit(main())
|