-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscanner.py
More file actions
188 lines (134 loc) · 4.56 KB
/
scanner.py
File metadata and controls
188 lines (134 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import argparse
import ipaddress
import re
import sys
import json
import nmap
# Target validation
def validate_target(target):
# Check if valid IP address
try:
ipaddress.ip_address(target)
return True
except ValueError:
pass
# Check if valid hostname
hostname_regex = r"^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z]{2,})+$"
if re.match(hostname_regex, target):
return True
return False
# Nmap scan execution
def run_nmap_scan(target, profile):
scanner = nmap.PortScanner()
if profile == "quick":
arguments = "-T4 --top-ports 1000"
elif profile == "full":
arguments = "-p- -sV"
else:
raise ValueError("Unknown scan profile")
try:
print(f"[+] Running {profile} scan against {target}")
scanner.scan(hosts=target, arguments=arguments)
except nmap.PortScannerError as e:
print(f"[!] Nmap execution failed: {e}")
sys.exit(1)
return scanner
# Service risk insight mapping
def get_service_insight(port):
common_services = {
21: "FTP service exposed – check for anonymous access or weak credentials",
22: "SSH service exposed – check for weak authentication or outdated versions",
23: "Telnet service exposed – insecure plaintext protocol",
80: "HTTP service exposed – potential web attack surface",
443: "HTTPS service exposed – potential web attack surface",
3306: "Database service exposed – MySQL may be accessible remotely",
}
return common_services.get(port, "Review service exposure")
# Result parsing
def parse_scan_results(scanner, target, profile):
print("\n[+] Scan Results:")
results = {
"target": target,
"profile": profile,
"open_ports": [],
}
for host in scanner.all_hosts():
print(f"\nHost: {host}")
if "tcp" not in scanner[host]:
print(" No TCP services found.")
continue
for port in scanner[host]["tcp"]:
port_info = scanner[host]["tcp"][port]
if port_info["state"] != "open":
continue
service = port_info.get("name", "unknown")
version = port_info.get("version", "")
insight = get_service_insight(port)
# CLI output
print(f" Port {port}/tcp")
print(f" Service: {service}")
if version:
print(f" Version: {version}")
print(f" Insight: {insight}")
# Structured data record
port_record = {
"port": port,
"protocol": "tcp",
"service": service,
"version": version,
"insight": insight,
}
results["open_ports"].append(port_record)
return results
# TXT report
def write_txt_report(results):
filename = f"scan_{results['target']}.txt"
with open(filename, "w") as f:
f.write(f"Target: {results['target']}\n")
f.write(f"Scan Profile: {results['profile']}\n\n")
f.write("Open Ports:\n\n")
for port in results["open_ports"]:
f.write(f" Port {port['port']}/{port['protocol']}\n")
f.write(f" Service: {port['service']}\n")
if port["version"]:
f.write(f" Version: {port['version']}\n")
f.write(f" Insight: {port['insight']}\n\n")
print(f"[+] TXT report saved as {filename}")
# JSON report
def write_json_report(results):
filename = f"scan_{results['target']}.json"
with open(filename, "w") as f:
json.dump(results, f, indent=4)
print(f"[+] JSON report saved as {filename}")
# Main entry point
def main():
parser = argparse.ArgumentParser(
description="Python-based reconnaissance tool using Nmap"
)
parser.add_argument(
"--target",
required=True,
help="Target IP address or hostname to scan",
)
parser.add_argument(
"--profile",
choices=["quick", "full"],
required=True,
help="Scan profile to use (quick or full)",
)
args = parser.parse_args()
target = args.target
profile = args.profile
# Validate target before scanning
if not validate_target(target):
print("[!] Invalid target provided.")
sys.exit(1)
# Run scan
scanner = run_nmap_scan(target, profile)
# Parse results
results = parse_scan_results(scanner, target, profile)
# Write reports
write_txt_report(results)
write_json_report(results)
if __name__ == "__main__":
main()