Created
February 18, 2021 20:09
-
-
Save smhuda/1deb2cf4c0e24d531e3651b421dc9c15 to your computer and use it in GitHub Desktop.
Nmap to CSV Parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Nmap2CSV is a simple Python script to convert XML (-oX) Nmap or Masscan | |
output files to a single CSV spreadsheet which summarizes all hosts and open | |
ports in a table in IP,PORT1,PORT2,PORT3,...,PORTN format: The first row is | |
the header with all open ports found on the scanned hosts. In the following | |
rows the specified character (default X) marks if the given port was found | |
open on the given host. The script also generates per-target results which | |
includes version information, if it is available. | |
""" | |
__description__ = 'Nmap to CSV spreadsheet converter' | |
__author__ = 'Gabor Seljan' | |
__version__ = '0.2.1' | |
__date__ = '2016/11/02' | |
import os | |
import textwrap | |
import xml.etree.ElementTree as ET | |
from argparse import * | |
banner = (""" | |
_ _ ___ ___ _____ __ | |
| \\| |_ __ __ _ _ __|_ ) __/ __\\ \\ / / | |
| .` | ' \\/ _` | '_ \\/ / (__\\__ \\\\\\\\ V / | |
|_|\\_|_|_|_\\__,_| .__/___\\___|___/ \\_/ | |
|_| | |
Nmap to CSV spreadsheet converter | |
""") | |
print(banner) | |
parser = ArgumentParser( | |
formatter_class=RawDescriptionHelpFormatter, | |
description=__doc__ | |
) | |
parser.add_argument('-i', metavar='INPUT', default='.', | |
help='Scan output file or folder (default current folder)') | |
parser.add_argument('-p', metavar='PREFIX', default='nmap2csv', | |
help='prefix for output file names (default nmap2csv)') | |
parser.add_argument('-s', metavar='SUFFIX', default='tcp', | |
help='suffix for output file names (default tcp)') | |
parser.add_argument('-m', metavar='MARKER', default='X', | |
help='marker character (default X)') | |
args = parser.parse_args() | |
FILES = [] | |
ADDRS = [] | |
PORTS = set() | |
RESULTS = {} | |
OUTPUT = [] | |
if os.path.isdir(args.i): | |
FILES = [os.path.join(args.i, f) for f in os.listdir(args.i) if f.endswith('.xml')] | |
elif os.path.isfile(args.i) and args.i.endswith('.xml'): | |
FILES = [args.i] | |
if not FILES: | |
parser.print_help() | |
print('\\n[-] No XML output file(s) found!') | |
exit(1) | |
for filename in FILES: | |
root = ET.parse(filename).getroot() | |
if root.get('scanner') == 'nmap': | |
for host in root.findall('host'): | |
if host.find('status').get('state') == 'up': | |
addr = host.find('address').get('addr') | |
if addr not in ADDRS: | |
ADDRS.append(addr) | |
for port in host.find('ports').findall('port'): | |
if port.find('state').get('state') == 'open': | |
portid = port.get('portid') | |
PORTS.add(portid) | |
if port.find('service') is not None: | |
name = port.find('service').get('name') | |
product = port.find('service').get('product') | |
version = port.find('service').get('version') | |
else: | |
name = '' | |
product = '' | |
version = '' | |
if addr in RESULTS: | |
if portid not in RESULTS[addr].keys(): | |
RESULTS[addr][portid] = [name, product, version] | |
else: | |
RESULTS.update({addr: {portid: [name, product, version]}}) | |
else: | |
for host in root.findall('host'): | |
addr = host.find('address').get('addr') | |
if addr not in ADDRS: | |
ADDRS.append(addr) | |
for port in host.find('ports').findall('port'): | |
portid = port.get('portid') | |
PORTS.add(portid) | |
if addr in RESULTS: | |
if portid not in RESULTS[addr].keys(): | |
RESULTS[addr][portid] = ['', '', ''] | |
else: | |
RESULTS.update({addr: {portid: ['', '', '']}}) | |
ADDRS = sorted(ADDRS, key=lambda x: tuple(map(int, x.split('.')))) | |
PORTS = sorted(PORTS, key=int) | |
print('[+] Found {} open ports on {} hosts!'.format(len(PORTS), len(ADDRS))) | |
if PORTS: | |
output = ['0.0.0.0,' + ','.join(str(p) for p in PORTS)] | |
for addr in ADDRS: | |
row = addr + ',' | |
for portid in PORTS: | |
try: | |
if portid in RESULTS[addr].keys(): | |
row += args.m + ',' | |
else: | |
row += ',' | |
except KeyError: | |
pass | |
output.append(row) | |
with open('{}-summary-{}.csv'.format(args.p, args.s), 'w') as f: | |
for row in output: | |
f.write(row + '\\n') | |
print('[+] Summary results saved to {}'.format(f.name)) | |
for addr, ports in RESULTS.items(): | |
output = ['Port,Service,Product,Version'] | |
for port, info in sorted(ports.items(), key=lambda x: int(x[0])): | |
row = '%s,%s' % (port, ','.join(map(str, info))) | |
output.append(row) | |
with open('{}-{}-{}.csv'.format(args.p, addr, args.s), 'w') as f: | |
for row in output: | |
f.write(row + '\\n') | |
print('[+] Per-target results saved to {}'.format(f.name)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment