Skip to content

Commit 02faf50

Browse files
authored
Merge pull request #37 from f-froehlich/script-output
Resolve #36
2 parents d45b1d3 + 4c5bbb9 commit 02faf50

File tree

1 file changed

+72
-5
lines changed

1 file changed

+72
-5
lines changed

nmap3/nmapparser.py

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,11 @@ def parse_nmap_subnetscan(self, xml_root):
9494
for port in host.find("ports").findall("port"):
9595
port_attrib = port.attrib
9696
ports.append(
97-
{"port":port_attrib.get("portid"), "protocol":port_attrib.get("protocol"),
98-
"state":port.find("state").attrib.get("state")
97+
{
98+
"port": port_attrib.get("portid"),
99+
"protocol": port_attrib.get("protocol"),
100+
"state": port.find("state").attrib.get("state"),
101+
"scripts": self.parse_scripts(port.findall('script')) if port.findall('script') is not None else []
99102
}
100103
)
101104

@@ -179,6 +182,9 @@ def parse_nmap_idlescan(self, xml_root):
179182

180183
if open_ports.find('service') is not None:
181184
port_dict['service']=open_ports.find('service').attrib
185+
186+
if port.findall('script') is not None:
187+
open_ports['scripts'] = self.parse_scripts(port.findall('script'))
182188

183189
idle_scan["ports"]=port_dict
184190

@@ -299,9 +305,12 @@ def filter_top_ports(self, xmlroot):
299305
for key in port.find('state').attrib:
300306
open_ports[key]=port.find("state").attrib.get(key)
301307

302-
if port.find("service") is not None:
308+
if port.find("service") is not None:
303309
open_ports["service"]=port.find("service").attrib
304310

311+
if port.findall('script') is not None:
312+
open_ports['scripts'] = self.parse_scripts(port.findall('script'))
313+
305314
port_results.append(open_ports)
306315
port_result_dict[address]=port_results
307316

@@ -343,7 +352,10 @@ def filter_stealth_scan(self, xmlroot):
343352

344353
if port.find("extrareasons") is not None:
345354
for extra in port.findall("extrareasons"):
346-
open_ports["extrareasons"]=extra.attrib
355+
open_ports["extrareasons"]=extra.attrib
356+
357+
if port.findall('script') is not None:
358+
open_ports['scripts'] = self.parse_scripts(port.findall('script'))
347359

348360
port_results.append(open_ports)
349361
port_result_dict[address]=port_results
@@ -400,6 +412,9 @@ def version_parser(self, xmlroot):
400412
cpe_list = []
401413
cpe_list.append({"cpe": cp.text})
402414
service["cpe"] = cpe_list
415+
if port.findall('script') is not None:
416+
service['scripts'] = self.parse_scripts(port.findall('script'))
417+
403418
services_result.append(service)
404419

405420
service_version_dict[address] = services_result
@@ -434,4 +449,56 @@ def os_identifier_parser(self, xmlroot):
434449
raise(e)
435450
else:
436451
return os_identified
437-
452+
453+
def parse_scripts(self, scripts_xml):
454+
scripts = []
455+
456+
for script_xml in scripts_xml:
457+
script_name = script_xml.attrib.get('id')
458+
raw_output = script_xml.attrib.get('output')
459+
460+
data = self.convert_xml_elements(script_xml)
461+
if script_xml.findall('table') is not None:
462+
tables = script_xml.findall('table')
463+
child_data = self.convert_xml_tables(tables)
464+
for k in child_data:
465+
if {} != k:
466+
data[k] = child_data[k]
467+
468+
scripts.append({
469+
'name': script_name,
470+
'raw': raw_output,
471+
'data': data
472+
})
473+
474+
return scripts
475+
476+
def convert_xml_tables(self, xml_tables):
477+
data = {}
478+
for xml_table in xml_tables:
479+
key = xml_table.attrib.get('key')
480+
child_data = self.convert_xml_elements(xml_table)
481+
if key is None:
482+
if {} != child_data:
483+
a = data.get('children', [])
484+
data['children'] = a + [child_data]
485+
else:
486+
if xml_table.findall('table') is not None:
487+
data[key] = self.convert_xml_tables(xml_table.findall('table'))
488+
if {} != child_data:
489+
a = data.get(key, {})
490+
b = a.get('children', [])
491+
a['children'] = b + [child_data]
492+
493+
return data
494+
495+
def convert_xml_elements(self, xml_obj):
496+
elements = {}
497+
elem_counter = 0
498+
for elem in xml_obj.findall('elem'):
499+
if None == elem.attrib.get('key'):
500+
elements[elem_counter] = elem.text
501+
else:
502+
elements[elem.attrib.get('key')] = elem.text
503+
elem_counter += 1
504+
return elements

0 commit comments

Comments
 (0)