-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathnmap2target
More file actions
executable file
·200 lines (177 loc) · 8.1 KB
/
nmap2target
File metadata and controls
executable file
·200 lines (177 loc) · 8.1 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
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/usr/bin/env python3
###########
# IMPORTS #
###########
import sys
import argparse
import os
import socket
import re
from urllib.parse import urlparse
try:
import xml.etree.cElementTree as ElementTree
except ImportError:
import xml.etree.ElementTree as ElementTree
#############
# FUNCTIONS #
#############
def error(*objects):
print(*objects, file=sys.stderr)
def info(*objects):
print(*objects, file=sys.stdout)
def check_file(xml_file):
if not os.path.exists(xml_file):
error("File '%s' does not exist." % xml_file)
exit(1)
if not os.access(xml_file, os.R_OK):
error("File '%s' is not readable." % xml_file)
exit(1)
def normalize_service(service, tunnel):
if service.startswith('http-') or service.endswith('http') or service == 'alt-http':
service = 'http'
if service.startswith('https') or service.endswith('https'):
service = 'https'
if tunnel == 'ssl':
if service.startswith('http') or service == 'upnp' or service == 'socks5' or service == 'alt-http':
service = 'https'
return service
def print_targets(xml_files, protocol_regex, service_regex, tunnel_regex, product_regex, service_prefix, hostnames):
targets = set()
for xml_file in xml_files:
check_file(xml_file)
xml = ElementTree.parse(xml_file)
try:
for host in xml.findall('host'):
address = host.find('address').get('addr', "")
status_xml = host.find('status', "")
status = status_xml.get('state') if status_xml is not None else None
if status == 'up':
for port in host.find('ports').findall('port'):
protocol = port.get('protocol', "")
portid = port.get('portid', "")
state = port.find('state').get('state', "")
if state == 'open':
service_xml = port.find('service')
if service_xml is None:
continue
service = service_xml.get('name', "")
tunnel = service_xml.get('tunnel', "")
product = service_xml.get('product', "")
service = normalize_service(service, tunnel)
protocol_result, service_result, tunnel_result, product_result = True, True, True, True
if protocol_regex and not re.search(protocol_regex, protocol, re.IGNORECASE):
protocol_result = False
if service_regex and not re.search(service_regex, service, re.IGNORECASE):
service_result = False
if tunnel_regex and not re.search(tunnel_regex, tunnel, re.IGNORECASE):
tunnel_result = False
if product_regex and not re.search(product_regex, product, re.IGNORECASE):
product_result = False
if protocol_result and service_result and tunnel_result and product_result:
if not service_prefix:
targets.add("%s:%s" % (address, portid))
for pair in hostnames:
hip, hname = pair.split(',')
if hip == address:
targets.add("%s:%s" % (hname, portid))
else:
targets.add("%s://%s:%s" % (service, address, portid))
for pair in hostnames:
hip, hname = pair.split(',')
if hip == address:
targets.add("%s://%s:%s" % (service, hname, portid))
except AttributeError as e:
error("Error parsing file '%s', %s. Skipping!" % (xml, e))
continue
#if not service_prefix:
# for target in sorted(targets, key=lambda item: socket.inet_aton(item.split(':', 1)[0])):
# print(target)
#else:
# for target in sorted(targets, key=lambda item: socket.inet_aton(urlparse(item).netloc.split(':', 1)[0])):
print(target)
for target in targets:
print(target)
def print_services(xml_files):
services = set()
for xml_file in xml_files:
check_file(xml_file)
xml = ElementTree.parse(xml_file)
try:
for host in xml.findall('host'):
status_xml = host.find('status', "")
status = status_xml.get('state') if status_xml is not None else None
if status == 'up':
for port in host.find('ports').findall('port'):
state = port.find('state').get('state', "")
if state == 'open':
service_xml = port.find('service')
if service_xml is None:
continue
service = service_xml.get('name', "")
tunnel = service_xml.get('tunnel', "")
service = normalize_service(service, tunnel)
services.add(service)
except AttributeError as e:
error("Error parsing file '%s', %s. Skipping!" % (xml, e))
continue
for service in sorted(list(services)):
print(service)
########
# MAIN #
########
if __name__ == '__main__':
desc = 'Parse Nmap xml output and print out targets (ip_address:port) based on supplied filters.'
parser = argparse.ArgumentParser(description=desc)
parser.add_argument('files',
action='store',
nargs='+',
help='nmap xml file(s) to parse',
metavar='INPUT')
parser.add_argument('-p', '--protocol',
action='store',
help='filter targets by protocol name',
metavar='REGEX',
default=None)
parser.add_argument('-s', '--service',
action='store',
help='filter targets by service name',
metavar='REGEX',
default=None)
parser.add_argument('-t', '--tunnel',
action='store',
help='filter targets by tunnel name',
metavar='REGEX',
default=None)
parser.add_argument('-n', '--name',
action='store',
help='filter targets by product name',
metavar='REGEX',
default=None)
parser.add_argument('-x', '--prefix',
action='store_true',
help='prefix target with service name e.g. service://target')
parser.add_argument('-l', '--list',
action='store_true',
help='list services found')
parser.add_argument('-m', '--hostnames',
action='store',
help='a comma seperated list of IP addresses and corresponding hostnames, include hostname in output if IP address match',
metavar='FILE',
default=None)
args = parser.parse_args()
for xml in args.files:
if not os.path.isfile(xml):
error("File '%s' does not exist." % xml)
exit(1)
if not os.access(xml, os.R_OK):
error("File '%s' is not readable." % xml)
exit(1)
if args.hostnames:
with open(args.hostnames) as fp:
hostnames = [line.strip() for line in fp if len(line.strip())>0 and line[0] != '#']
else:
hostnames = list()
if args.list:
print_services(args.files)
else:
print_targets(args.files, args.protocol, args.service, args.tunnel, args.name, args.prefix, hostnames)