ghostnet 1.2.1__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.
ghostnet/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ """GhostNet - Advanced Network Scanner."""
3
+ from .constants import VERSION as __version__
4
+ from .cli import main
5
+
6
+ __all__ = ["main", "__version__"]
ghostnet/__main__.py ADDED
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ import sys
3
+ import time
4
+ from .cli import main
5
+ from .constants import Colors
6
+
7
+
8
+ def _run():
9
+ exit_code = 0
10
+ try:
11
+ exit_code = main()
12
+ except KeyboardInterrupt:
13
+ print(f"\n{Colors.BRIGHT_RED}Program terminated by user.{Colors.RESET}")
14
+ exit_code = 130
15
+ except Exception as e:
16
+ print(f"\n{Colors.BRIGHT_RED}An unexpected error occurred: {e}{Colors.RESET}")
17
+ exit_code = 1
18
+ finally:
19
+ if len(sys.argv) <= 1:
20
+ time.sleep(1.5)
21
+ sys.exit(exit_code)
22
+
23
+
24
+ if __name__ == "__main__":
25
+ _run()
ghostnet/cli.py ADDED
@@ -0,0 +1,415 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ import sys
4
+ import socket
5
+ import ssl
6
+ import re
7
+ import json
8
+ import time
9
+ import random
10
+ import struct
11
+ import uuid
12
+ import copy
13
+ import errno
14
+ import logging
15
+ import threading
16
+ import getpass
17
+ import platform
18
+ import ipaddress
19
+ import asyncio
20
+ import xml.etree.ElementTree as ET
21
+ from datetime import datetime, timedelta
22
+ from concurrent.futures import ThreadPoolExecutor
23
+ from urllib.parse import urljoin, urlparse
24
+ from typing import List, Dict, Any, Tuple, Optional, Union
25
+ import pytz
26
+ import requests
27
+ import urllib3
28
+ from bs4 import BeautifulSoup
29
+
30
+ from .constants import *
31
+ import argparse
32
+ from .config import Config
33
+ from .parsing import parse_target_spec, parse_port_spec
34
+ from .engine import Scanner
35
+ from .reporting import Reporter
36
+ from .netmap import NetworkMapper, format_topology
37
+ from .menu import interactive_main
38
+
39
+ def parse_args():
40
+ parser = argparse.ArgumentParser(
41
+ prog="ghostnet",
42
+ description="GhostNet - Advanced Network Scanner",
43
+ formatter_class=argparse.RawDescriptionHelpFormatter,
44
+ epilog="""\
45
+ examples:
46
+ ghostnet -t 192.168.1.1 scan common ports
47
+ ghostnet -t 192.168.1.0/24 -p- whole subnet, all 65535 ports
48
+ ghostnet -t host -A aggressive: -sV -O -b
49
+ ghostnet -t host -sV -T4 version detection, fast timing
50
+ ghostnet -t 192.168.1.0/24 -sn host discovery (ping sweep) only
51
+ sudo ghostnet -t host --syn-scan SYN scan (needs scapy/root)
52
+ ghostnet -t host -oA results write results.txt/.json/.xml
53
+ ghostnet --update-db refresh the local NVD database
54
+
55
+ Run with no arguments for an interactive menu.
56
+ """,
57
+ )
58
+
59
+ # Target specification
60
+ target_group = parser.add_argument_group("Target Selection")
61
+ target_group.add_argument("-t", "--target", dest="targets", action="append",
62
+ help="Target IP address, hostname, or network (CIDR)")
63
+ target_group.add_argument("-iL", "--input-file", dest="input_file",
64
+ help="Input from file containing targets (one per line)")
65
+
66
+ # Port specification
67
+ port_group = parser.add_argument_group("Port Selection")
68
+ port_group.add_argument("-p", "--ports", dest="ports",
69
+ help="Port(s) to scan (e.g., 22,80,443 or 1-1000; '-' for all 65535)")
70
+ port_group.add_argument("--top-ports", dest="top_ports", type=int,
71
+ help="Scan the top N most common ports")
72
+
73
+ # Scan types
74
+ scan_group = parser.add_argument_group("Scan Techniques")
75
+ scan_group.add_argument("-sS", "--syn-scan", dest="syn_scan", action="store_true",
76
+ help="TCP SYN scan (requires root/admin privileges)")
77
+ scan_group.add_argument("-sT", "--tcp-scan", dest="tcp_scan", action="store_true",
78
+ help="TCP connect scan")
79
+ scan_group.add_argument("-sU", "--udp-scan", dest="udp_scan", action="store_true",
80
+ help="UDP scan")
81
+ scan_group.add_argument("-sF", "--fast", dest="fast_mode", action="store_true",
82
+ help="Fast scan mode")
83
+ scan_group.add_argument("-sn", "--ping-scan", dest="ping_scan", action="store_true",
84
+ help="Host discovery only (ping sweep); no port scan")
85
+ scan_group.add_argument("-Pn", "--no-ping", dest="no_ping", action="store_true",
86
+ help="Skip host discovery; treat all hosts as online "
87
+ "(accepted for nmap compatibility)")
88
+
89
+ # Service and OS detection
90
+ service_group = parser.add_argument_group("Service/OS Detection")
91
+ service_group.add_argument("-sV", "--service-version", dest="service_detection", action="store_true",
92
+ help="Probe open ports to determine service/version info")
93
+ service_group.add_argument("-O", "--os-detection", dest="os_detection", action="store_true",
94
+ help="Enable OS detection")
95
+ service_group.add_argument("-b", "--banner", dest="banner_grabbing", action="store_true",
96
+ help="Perform banner grabbing on open ports")
97
+ service_group.add_argument("-A", "--aggressive", dest="aggressive", action="store_true",
98
+ help="Aggressive scan: enable -sV, -O and -b")
99
+
100
+ # Timing and performance
101
+ timing_group = parser.add_argument_group("Timing and Performance")
102
+ timing_group.add_argument("-T", dest="timing", type=int, choices=range(6),
103
+ help="Timing template: -T0 (paranoid) .. -T5 (insane)")
104
+ timing_group.add_argument("--min-rate", dest="min_rate", type=int,
105
+ help="Send packets no slower than <number> per second")
106
+ timing_group.add_argument("--max-rate", dest="max_rate", type=int,
107
+ help="Send packets no faster than <number> per second")
108
+ timing_group.add_argument("--max-retries", dest="max_retries", type=int, default=1,
109
+ help="Maximum number of retries")
110
+ timing_group.add_argument("--timeout", dest="timeout", type=float, default=None,
111
+ help="Set timeout in seconds")
112
+ timing_group.add_argument("--threads", dest="threads", type=int, default=None,
113
+ help="Number of concurrent threads")
114
+
115
+ # Evasion techniques
116
+ evasion_group = parser.add_argument_group("Evasion and Spoofing")
117
+ evasion_group.add_argument("--spoof-mac", dest="spoof_mac",
118
+ help="Spoof MAC address")
119
+ evasion_group.add_argument("--spoof-ip", dest="spoof_ip",
120
+ help="Spoof source IP address")
121
+ evasion_group.add_argument("--source-port", dest="source_port", type=int,
122
+ help="Use specified source port")
123
+ evasion_group.add_argument("--data-length", dest="data_length", type=int,
124
+ help="Append random data to sent packets")
125
+ evasion_group.add_argument("--ttl", dest="ttl", type=int,
126
+ help="Set IP time-to-live field")
127
+ evasion_group.add_argument("--randomize", dest="randomize", action="store_true",
128
+ help="Randomize target and port order")
129
+ evasion_group.add_argument("--fragmentation", dest="fragmentation", action="store_true",
130
+ help="Fragment IP packets")
131
+ evasion_group.add_argument("--scan-delay", dest="scan_delay", type=float, default=0,
132
+ help="Add delay between packets")
133
+
134
+ # Output options
135
+ output_group = parser.add_argument_group("Output")
136
+ output_group.add_argument("-v", "--verbose", dest="verbose", action="store_true",
137
+ help="Increase verbosity level")
138
+ output_group.add_argument("-q", "--quiet", dest="quiet", action="store_true",
139
+ help="Quiet mode")
140
+ output_group.add_argument("-oN", "--output-normal", dest="output_normal",
141
+ help="Output in normal format to the given filename")
142
+ output_group.add_argument("-oX", "--output-xml", dest="output_xml",
143
+ help="Output in XML format to the given filename")
144
+ output_group.add_argument("-oJ", "--output-json", dest="output_json",
145
+ help="Output in JSON format to the given filename")
146
+ output_group.add_argument("-oA", "--output-all", dest="output_all",
147
+ help="Write all three formats to BASENAME.txt/.json/.xml")
148
+ output_group.add_argument("--no-color", dest="no_color", action="store_true",
149
+ help="Disable colored output")
150
+
151
+ # Misc options
152
+ misc_group = parser.add_argument_group("Misc")
153
+ misc_group.add_argument("--interface", dest="interface",
154
+ help="Use specified network interface")
155
+ misc_group.add_argument("-V", "--version", action="version", version=f"GhostNet {VERSION}")
156
+ misc_group.add_argument("--vuln-scan", dest="vuln_scan", action="store_true",
157
+ help="Perform basic vulnerability checks")
158
+ misc_group.add_argument("--traceroute", "--map", dest="network_map", action="store_true",
159
+ help="Map network topology via traceroute (requires scapy/root)")
160
+ misc_group.add_argument("--update-db", dest="update_db", action="store_true",
161
+ help="Refresh the local NVD vulnerability database and exit "
162
+ "(needs an NVD API key; see --help)")
163
+ misc_group.add_argument("-n", "--no-dns", dest="no_dns", action="store_true",
164
+ help="Disable DNS resolution")
165
+
166
+ return parser.parse_args()
167
+
168
+
169
+ def configure_from_args(args):
170
+ """Configure the scanner from command line arguments"""
171
+ config = Config()
172
+
173
+ # Parse targets
174
+ if args.targets:
175
+ for target_spec in args.targets:
176
+ config.targets.extend(parse_target_spec(target_spec))
177
+
178
+ if args.input_file:
179
+ try:
180
+ with open(args.input_file, 'r') as f:
181
+ for line in f:
182
+ line = line.strip()
183
+ if line and not line.startswith('#'):
184
+ config.targets.extend(parse_target_spec(line))
185
+ except Exception as e:
186
+ print(f"Error reading target file: {e}")
187
+ sys.exit(1)
188
+
189
+ # Parse ports
190
+ if args.ports:
191
+ config.ports = parse_port_spec(args.ports)
192
+ elif args.top_ports:
193
+ # Take the top N most common ports
194
+ top_n = min(args.top_ports, len(COMMON_PORTS))
195
+ config.ports = list(COMMON_PORTS.keys())[:top_n]
196
+
197
+ # Scan type
198
+ if args.syn_scan:
199
+ config.scan_type = "tcp_syn"
200
+ elif args.udp_scan:
201
+ config.scan_type = "udp"
202
+ else:
203
+ config.scan_type = "tcp_connect" # Default
204
+
205
+ # Timing template (-T0..-T5): a baseline for timeout/threads/scan-delay
206
+ # that explicit flags below still override.
207
+ if args.timing is not None:
208
+ timeout, threads, delay = TIMING_TEMPLATES[args.timing]
209
+ config.timeout = timeout
210
+ config.threads = threads
211
+ config.scan_delay = delay
212
+
213
+ # Performance settings (explicit flags win over the timing template).
214
+ if args.timeout is not None:
215
+ config.timeout = args.timeout
216
+ if args.threads is not None:
217
+ config.threads = args.threads
218
+ if args.scan_delay:
219
+ config.scan_delay = args.scan_delay
220
+ config.min_rate = args.min_rate
221
+ config.max_rate = args.max_rate
222
+ if args.max_retries is not None:
223
+ config.max_retries = args.max_retries
224
+
225
+ # Detection features. -A (aggressive) implies -sV, -O and -b.
226
+ config.service_detection = args.service_detection or args.aggressive
227
+ config.os_detection = args.os_detection or args.aggressive
228
+ config.banner_grabbing = args.banner_grabbing or args.aggressive
229
+ config.vuln_check = args.vuln_scan
230
+ config.network_map = args.network_map
231
+
232
+ # Host discovery.
233
+ config.ping_scan = args.ping_scan # -sn: discovery only
234
+ config.no_ping = args.no_ping # -Pn: skip discovery
235
+
236
+ # Fast mode
237
+ if args.fast_mode:
238
+ config.fast_mode = True
239
+ config.timeout = 0.5
240
+ config.threads = 100
241
+
242
+ # Evasion techniques
243
+ if args.spoof_ip:
244
+ config.source_ip = args.spoof_ip
245
+ if args.spoof_mac:
246
+ config.source_mac = args.spoof_mac
247
+ if args.source_port:
248
+ config.source_port = args.source_port
249
+ if args.ttl:
250
+ config.ttl = args.ttl
251
+ config.randomize = args.randomize
252
+ config.fragmentation = args.fragmentation
253
+
254
+ # DNS resolution
255
+ config.dns_resolution = not args.no_dns
256
+
257
+ # Interface
258
+ if args.interface:
259
+ config.interface = args.interface
260
+
261
+ # Output settings
262
+ config.verbose = args.verbose
263
+ if args.quiet:
264
+ config.log_level = logging.ERROR
265
+ elif args.verbose:
266
+ config.log_level = logging.DEBUG
267
+
268
+ # Output format and file
269
+ if args.output_xml:
270
+ config.output_file = args.output_xml
271
+ config.output_format = "xml"
272
+ elif args.output_json:
273
+ config.output_file = args.output_json
274
+ config.output_format = "json"
275
+ elif args.output_normal:
276
+ config.output_file = args.output_normal
277
+ config.output_format = "text"
278
+
279
+ return config
280
+
281
+
282
+ def update_vuln_db():
283
+ """Refresh the local NVD vulnerability database (wraps vuln.py).
284
+
285
+ Returns an exit code. Requires an NVD API key (NVD_API_KEY env var or a
286
+ .env file); see https://nvd.nist.gov/developers/request-an-api-key.
287
+ """
288
+ try:
289
+ import vuln
290
+ except Exception as e:
291
+ print(f"{Colors.BRIGHT_RED}Could not load the NVD updater: {e}{Colors.RESET}",
292
+ file=sys.stderr)
293
+ return 1
294
+
295
+ print(f"{Colors.BRIGHT_CYAN}Refreshing the NVD vulnerability database...{Colors.RESET}")
296
+ try:
297
+ vuln.main()
298
+ except Exception as e:
299
+ # NVDVulnerabilityFetcher raises when no API key is configured.
300
+ print(f"{Colors.BRIGHT_RED}Database update failed: {e}{Colors.RESET}",
301
+ file=sys.stderr)
302
+ return 1
303
+ return 0
304
+
305
+
306
+
307
+ def host_is_up(target, timeout=1.0):
308
+ """Lightweight TCP host discovery: an open port OR a refused connection
309
+ means the host is up; only a timeout/unreachable counts as down. Uses
310
+ connect_ex (which returns an error code rather than raising). No root
311
+ required."""
312
+ reachable = {0, errno.ECONNREFUSED, errno.ECONNRESET}
313
+ for port in (80, 443, 22, 445, 3389):
314
+ try:
315
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
316
+ sock.settimeout(timeout)
317
+ if sock.connect_ex((target, port)) in reachable:
318
+ return True
319
+ except OSError:
320
+ continue
321
+ return False
322
+
323
+
324
+
325
+ def discover_hosts(targets, timeout=1.0):
326
+ """Return the subset of targets that appear to be online."""
327
+ up = []
328
+ for target in targets:
329
+ if host_is_up(target, timeout):
330
+ up.append(target)
331
+ return up
332
+
333
+
334
+
335
+ def scan_summary(results, elapsed):
336
+ """One-line nmap-style summary of a results dict."""
337
+ hosts = len(results)
338
+ open_ports = sum(len(d.get("open_ports", {})) for d in results.values())
339
+ return (f"GhostNet done: {hosts} host(s) scanned, {open_ports} open port(s) "
340
+ f"in {elapsed:.2f}s")
341
+
342
+
343
+
344
+ def run_cli(args):
345
+ """Run a scan from parsed command-line arguments. Returns an exit code."""
346
+ if args.no_color:
347
+ Colors.disable()
348
+
349
+ # Database refresh is a standalone action (no targets needed).
350
+ if getattr(args, "update_db", False):
351
+ return update_vuln_db()
352
+
353
+ config = configure_from_args(args)
354
+
355
+ if not config.targets:
356
+ print(f"{Colors.BRIGHT_RED}Error: no targets specified. "
357
+ f"Use -t <target> or -iL <file>.{Colors.RESET}", file=sys.stderr)
358
+ return 2
359
+
360
+ # -sn: host discovery only, then exit.
361
+ if config.ping_scan:
362
+ up = discover_hosts(config.targets, config.timeout)
363
+ print(f"{Colors.BRIGHT_CYAN}Host discovery:{Colors.RESET}")
364
+ for target in config.targets:
365
+ status = (f"{Colors.BRIGHT_GREEN}up{Colors.RESET}" if target in up
366
+ else f"{Colors.BRIGHT_BLACK}down{Colors.RESET}")
367
+ print(f" {target:<18} {status}")
368
+ print(f"\n{len(up)}/{len(config.targets)} host(s) up")
369
+ return 0
370
+
371
+ # For multi-host scans, skip hosts that are down unless -Pn was given.
372
+ if not config.no_ping and len(config.targets) > 1:
373
+ up = discover_hosts(config.targets, config.timeout)
374
+ if up:
375
+ config.targets = up
376
+
377
+ start = time.time()
378
+ scanner = Scanner(config)
379
+ scanner.initialize()
380
+ results = scanner.run()
381
+ elapsed = time.time() - start
382
+
383
+ reporter = Reporter(config, results)
384
+ print(reporter.generate_report())
385
+
386
+ # Output files: -oA writes all three formats; otherwise the single
387
+ # configured format.
388
+ if args.output_all:
389
+ for fmt, ext in (("text", "txt"), ("json", "json"), ("xml", "xml")):
390
+ config.output_format = fmt
391
+ config.output_file = f"{args.output_all}.{ext}"
392
+ Reporter(config, results).save_report()
393
+ elif config.output_file:
394
+ reporter.save_report()
395
+
396
+ # Optional network topology mapping (traceroute).
397
+ if config.network_map:
398
+ mapper = NetworkMapper(config)
399
+ topology = mapper.map_network(config.targets)
400
+ print("\n" + format_topology(topology))
401
+
402
+ print(f"\n{Colors.BRIGHT_WHITE}{scan_summary(results, elapsed)}{Colors.RESET}")
403
+ return 0
404
+
405
+ # Network Mapper class for network topology mapping
406
+
407
+
408
+ def main():
409
+ """Entry point: dispatch to the CLI when arguments are given, otherwise
410
+ launch the interactive menu."""
411
+ if len(sys.argv) > 1:
412
+ args = parse_args()
413
+ return run_cli(args)
414
+ interactive_main()
415
+ return 0
ghostnet/config.py ADDED
@@ -0,0 +1,66 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ import sys
4
+ import socket
5
+ import ssl
6
+ import re
7
+ import json
8
+ import time
9
+ import random
10
+ import struct
11
+ import uuid
12
+ import copy
13
+ import errno
14
+ import logging
15
+ import threading
16
+ import getpass
17
+ import platform
18
+ import ipaddress
19
+ import asyncio
20
+ import xml.etree.ElementTree as ET
21
+ from datetime import datetime, timedelta
22
+ from concurrent.futures import ThreadPoolExecutor
23
+ from urllib.parse import urljoin, urlparse
24
+ from typing import List, Dict, Any, Tuple, Optional, Union
25
+ import pytz
26
+ import requests
27
+ import urllib3
28
+ from bs4 import BeautifulSoup
29
+
30
+ from .constants import *
31
+
32
+ class Config:
33
+ def __init__(self):
34
+ self.scan_type = "tcp_syn" # Default scan type
35
+ self.ports = []
36
+ self.targets = []
37
+ self.timeout = 1.0
38
+ self.threads = 50
39
+ self.verbose = False
40
+ self.output_file = None
41
+ self.output_format = "text"
42
+ self.randomize = False
43
+ self.scan_delay = 0
44
+ self.service_detection = False
45
+ self.os_detection = False
46
+ self.banner_grabbing = False
47
+ self.evasion_level = 0
48
+ self.interface = None
49
+ self.source_port = None
50
+ self.ttl = None
51
+ self.source_ip = None
52
+ self.source_mac = None
53
+ self.fragmentation = False
54
+ self.log_level = logging.INFO
55
+ self.vuln_check = False
56
+ self.dns_resolution = True
57
+ self.scan_id = datetime.now().strftime("%Y%m%d%H%M%S")
58
+ self.fast_mode = False
59
+ self.network_map = False
60
+ self.min_rate = None # packets/sec floor (raises the max cap)
61
+ self.max_rate = None # packets/sec cap (None = unlimited)
62
+ self.max_retries = 1 # retries for lossy scans (UDP / SYN)
63
+ self.ping_scan = False # -sn: host discovery only
64
+ self.no_ping = False # -Pn: skip host discovery
65
+
66
+ # CVE intergration using NVD API
ghostnet/constants.py ADDED
@@ -0,0 +1,167 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Shared constants, feature flags, and optional-dependency symbols.
3
+
4
+ scapy/impacket symbols are defined as None when the libraries are absent so
5
+ that `from .constants import *` always resolves in every submodule; the
6
+ HAS_SCAPY / HAS_IMPACKET guards ensure the None values are never called.
7
+ """
8
+ import sys
9
+ import os
10
+
11
+ # UTF-8 on the Windows console.
12
+ if os.name == 'nt':
13
+ import codecs
14
+ sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach())
15
+ sys.stderr = codecs.getwriter('utf-8')(sys.stderr.detach())
16
+
17
+ try:
18
+ from impacket import smb, smb3, nmb, nt_errors
19
+ from impacket.smbconnection import SMBConnection
20
+ HAS_IMPACKET = True
21
+ except ImportError:
22
+ HAS_IMPACKET = False
23
+ smb = smb3 = nmb = nt_errors = None
24
+ SMBConnection = None
25
+ print("[!] impacket not available - SMB features disabled "
26
+ "(pipx inject ghostnet impacket, or pip install impacket)",
27
+ file=sys.stderr)
28
+
29
+ try:
30
+ from scapy.all import (
31
+ IP, TCP, UDP, ICMP, Ether, sr1, srp1, send, sendp, conf,
32
+ sniff, rdpcap, wrpcap, RandShort,
33
+ )
34
+ HAS_SCAPY = True
35
+ except ImportError:
36
+ HAS_SCAPY = False
37
+ IP = TCP = UDP = ICMP = Ether = sr1 = srp1 = send = sendp = conf = None
38
+ sniff = rdpcap = wrpcap = RandShort = None
39
+ print("[!] scapy not available - SYN/OS/traceroute disabled "
40
+ "(pipx inject ghostnet scapy, or pip install scapy)",
41
+ file=sys.stderr)
42
+
43
+
44
+ class Colors:
45
+ RESET = "\033[0m"
46
+ BLACK = "\033[30m"
47
+ RED = "\033[31m"
48
+ GREEN = "\033[32m"
49
+ YELLOW = "\033[33m"
50
+ BLUE = "\033[34m"
51
+ MAGENTA = "\033[35m"
52
+ CYAN = "\033[36m"
53
+ WHITE = "\033[37m"
54
+ BRIGHT_BLACK = "\033[90m"
55
+ BRIGHT_RED = "\033[91m"
56
+ BRIGHT_GREEN = "\033[92m"
57
+ BRIGHT_YELLOW = "\033[93m"
58
+ BRIGHT_BLUE = "\033[94m"
59
+ BRIGHT_MAGENTA = "\033[95m"
60
+ BRIGHT_CYAN = "\033[96m"
61
+ BRIGHT_WHITE = "\033[97m"
62
+ RESET = "\033[0m"
63
+ BLACK = "\033[30m"
64
+ RED = "\033[31m"
65
+ GREEN = "\033[32m"
66
+ YELLOW = "\033[33m"
67
+ BLUE = "\033[34m"
68
+ MAGENTA = "\033[35m"
69
+ CYAN = "\033[36m"
70
+ WHITE = "\033[37m"
71
+ BOLD = "\033[1m"
72
+ UNDERLINE = "\033[4m"
73
+
74
+ @classmethod
75
+ def disable(cls):
76
+ """Blank out every ANSI code (used by --no-color)."""
77
+ for name in list(vars(cls)):
78
+ value = getattr(cls, name)
79
+ if isinstance(value, str) and value.startswith("\033"):
80
+ setattr(cls, name, "")
81
+
82
+ # Constants
83
+
84
+ VERSION = "1.2.1"
85
+ BANNER = f"""{Colors.BRIGHT_CYAN}
86
+ ╔═══════════════════════════════════════════════════════════╗
87
+ ║ ║
88
+ ║ ░██████╗░██╗░░██╗░█████╗░░██████╗████████╗ ║
89
+ ║ ██╔════╝░██║░░██║██╔══██╗██╔════╝╚══██╔══╝ ║
90
+ ║ ██║░░██╗░███████║██║░░██║╚█████╗░░░░██║░░░ ║
91
+ ║ ██║░░╚██╗██╔══██║██║░░██║░╚═══██╗░░░██║░░░ ║
92
+ ║ ╚██████╔╝██║░░██║╚█████╔╝██████╔╝░░░██║░░░ ║
93
+ ║ ░╚═════╝░╚═╝░░╚═╝░╚════╝░╚═════╝░░░░╚═╝░░░ ║
94
+ ║ ║
95
+ ║ ███╗░░██╗███████╗████████╗ ║
96
+ ║ ████╗░██║██╔════╝╚══██╔══╝ ║
97
+ ║ ██╔██╗██║█████╗░░░░░██║░░░ ║
98
+ ║ ██║╚████║██╔══╝░░░░░██║░░░ ║
99
+ ║ ██║░╚███║███████╗░░░██║░░░ ║
100
+ ║ ╚═╝░░╚══╝╚══════╝░░░╚═╝░░░ ║
101
+ ║ ║
102
+ ╚═══════════════════════════════════════════════════════════╝{Colors.RESET}
103
+
104
+ {Colors.BRIGHT_WHITE}Advanced Network Scanner v{VERSION}
105
+ {Colors.BRIGHT_GREEN}» Welcome to Ghost Net >==< «{Colors.RESET}"""
106
+
107
+ # Common ports to scan by default
108
+ COMMON_PORTS = {
109
+ 21: "FTP",
110
+ 22: "SSH",
111
+ 23: "Telnet",
112
+ 25: "SMTP",
113
+ 53: "DNS",
114
+ 80: "HTTP",
115
+ 110: "POP3",
116
+ 111: "RPC",
117
+ 135: "MSRPC",
118
+ 139: "NetBIOS",
119
+ 143: "IMAP",
120
+ 443: "HTTPS",
121
+ 445: "SMB",
122
+ 993: "IMAPS",
123
+ 995: "POP3S",
124
+ 1433: "MSSQL",
125
+ 1521: "Oracle",
126
+ 3306: "MySQL",
127
+ 3389: "RDP",
128
+ 5432: "PostgreSQL",
129
+ 5900: "VNC",
130
+ 8080: "HTTP-Proxy",
131
+ 8443: "HTTPS-Alt"
132
+ }
133
+
134
+ # Common service fingerprints for basic service detection
135
+ SERVICE_FINGERPRINTS = {
136
+ b"SSH-": "SSH",
137
+ b"HTTP/": "HTTP",
138
+ b"220 ": "FTP",
139
+ b"SMTP": "SMTP",
140
+ b"POP3": "POP3",
141
+ b"IMAP": "IMAP",
142
+ b"RFB ": "VNC",
143
+ b"Microsoft SQL Server": "MSSQL",
144
+ b"MySQL": "MySQL",
145
+ b"5432": "PostgreSQL",
146
+ }
147
+
148
+ # OS fingerprinting signatures based on TTL values (simplified)
149
+ OS_FINGERPRINTS = {
150
+ 64: "Linux/Unix",
151
+ 128: "Windows",
152
+ 255: "Cisco/Network Device",
153
+ 254: "Solaris/AIX"
154
+ }
155
+
156
+ # Configuration
157
+
158
+ TIMING_TEMPLATES = {
159
+ 0: (5.0, 1, 5.0), # paranoid
160
+ 1: (5.0, 1, 1.0), # sneaky
161
+ 2: (3.0, 10, 0.4), # polite
162
+ 3: (1.0, 50, 0.0), # normal (defaults)
163
+ 4: (0.5, 100, 0.0), # aggressive
164
+ 5: (0.3, 200, 0.0), # insane
165
+ }
166
+
167
+