#!/usr/bin/python

# Ndiff
#
# This programs reads two Nmap XML files and displays a list of their
# differences.
#
# Copyright 2008 Insecure.Com LLC
# Ndiff is distributed under the same license as Nmap. See the file COPYING or
# http://nmap.org/data/COPYING. See http://nmap.org/book/man-legal.html for more
# details.
#
# David Fifield
# based on a design by Michael Pattrick

import datetime
import difflib
import getopt
import sys
import time
import xml.sax
import xml.dom.minidom

verbose = False

NDIFF_XML_VERSION = u"1"

class Scan(object):
    """A single Nmap scan, corresponding to a single invocation of Nmap. It is a
    container for a list of hosts. It also has utility methods to load itself
    from an Nmap XML file."""
    def __init__(self):
        self.version = None
        self.start_date = None
        self.end_date = None
        self.hosts = []

    def find_host(self, id):
        for host in self.hosts:
            if host.get_id() == id:
                return host
        else:
            return None

    def load(self, f):
        """Load a scan from the Nmap XML in the file-like object f."""
        parser = xml.sax.make_parser()
        handler = NmapContentHandler(self)
        parser.setContentHandler(handler)
        parser.parse(f)

    def load_from_file(self, filename):
        """Load a scan from the Nmap XML file with the given filename."""
        f = open(filename, "r")
        try:
            self.load(f)
        finally:
            f.close()

class Host(object):
    """A single host, with a state, addresses, host names, a dict mapping port
    specs to Ports, and a list of OS matches. Host states are strings, or None
    for "unknown"."""
    def __init__(self):
        self.state = None
        self.addresses = []
        self.hostnames = []
        self.ports = {}
        self.extraports = {}
        self.os = []

    def get_id(self):
        """Return an id that is used to determine if hosts are "the same" across
        scans."""
        if len(self.addresses) > 0:
            return str(sorted(self.addresses)[0])
        if len(self.hostnames) > 0:
            return str(sorted(self.hostnames)[0])
        return id(self)

    def format_name(self):
        """Return a human-readable identifier for this host."""
        address_s = u", ".join(a.s for a in sorted(self.addresses))
        hostname_s = u", ".join(sorted(self.hostnames))
        if len(hostname_s) > 0:
            if len(address_s) > 0:
                return u"%s (%s)" % (hostname_s, address_s)
            else:
                return hostname_s
        elif len(address_s) > 0:
            return address_s
        else:
            return u"<no name>"

    def add_port(self, port):
        self.ports[port.spec] = port

    def add_address(self, address):
        if address not in self.addresses:
            self.addresses.append(address)

    def add_hostname(self, hostname):
        if hostname not in self.hostnames:
            self.hostnames.append(hostname)

    def is_extraports(self, state):
        return state is None or state in self.extraports

    def extraports_string(self):
        list = [(count, state) for (state, count) in self.extraports.items()]
        # Reverse-sort by count.
        list.sort(reverse = True)
        return u", ".join([u"%d %s ports" % (count, state) for (count, state) in list])

    def state_to_dom_fragment(self, document):
        frag = document.createDocumentFragment()
        if self.state is not None:
            elem = document.createElement(u"status")
            elem.setAttribute(u"state", self.state)
            frag.appendChild(elem)
        return frag

    def hostname_to_dom_fragment(self, document, hostname):
        frag = document.createDocumentFragment()
        elem = document.createElement(u"hostname")
        elem.setAttribute(u"name", hostname)
        frag.appendChild(elem)
        return frag

    def extraports_to_dom_fragment(self, document):
        frag = document.createDocumentFragment()
        for state, count in self.extraports.items():
            elem = document.createElement(u"extraports")
            elem.setAttribute(u"state", state)
            elem.setAttribute(u"count", unicode(count))
            frag.appendChild(elem)
        return frag

    def os_to_dom_fragment(self, document, os):
        frag = document.createDocumentFragment()
        elem = document.createElement(u"osmatch")
        elem.setAttribute(u"name", os)
        frag.appendChild(elem)
        return frag

    def to_dom_fragment(self, document):
        frag = document.createDocumentFragment()
        elem = document.createElement(u"host")

        if self.state is not None:
            elem.appendChild(self.state_to_dom_fragment(document))

        for addr in self.addresses:
            elem.appendChild(addr.to_dom_fragment(document))

        if len(self.hostnames) > 0:
            hostnames_elem = document.createElement(u"hostnames")
            for hostname in self.hostnames:
                hostnames_elem.appendChild(self.hostname_to_dom_fragment(document, hostname))
            elem.appendChild(hostnames_elem)

        ports_elem = document.createElement(u"ports")
        ports_elem.appendChild(self.extraports_to_dom_fragment(document))
        for port in sorted(self.ports.values()):
            if not self.is_extraports(port.state):
                ports_elem.appendChild(port.to_dom_fragment(document))
        if ports_elem.hasChildNodes():
            elem.appendChild(ports_elem)

        if len(self.os) > 0:
            os_elem = document.createElement(u"os")
            for os in self.os:
                os_elem.appendChild(self.os_to_dom_fragment(document, os))
            elem.appendChild(os_elem)

        frag.appendChild(elem)
        return frag

class Address(object):
    def __init__(self, s):
        self.s = s

    def __eq__(self, other):
        return self.__cmp__(other) == 0

    def __ne__(self, other):
        return not self.__eq__(other)

    def __hash__(self):
        return hash(self.sort_key())

    def __cmp__(self, other):
        return cmp(self.sort_key(), other.sort_key())

    def __str__(self):
        return str(self.s)

    def __unicode__(self):
        return self.s

    def new(type, s):
        if type == u"ipv4":
            return IPv4Address(s)
        elif type == u"ipv6":
            return IPv6Address(s)
        elif type == u"mac":
            return MACAddress(s)
        else:
            raise ValueError(u"Unknown address type %s." % type)
    new = staticmethod(new)

    def to_dom_fragment(self, document):
        frag = document.createDocumentFragment()
        elem = document.createElement(u"address")
        elem.setAttribute(u"addr", self.s)
        elem.setAttribute(u"addrtype", self.type)
        frag.appendChild(elem)
        return frag

# The sort_key method in the Address subclasses determines the order in which
# addresses are displayed. We do IPv4, then IPV6, then MAC.

class IPv4Address(Address):
    type = property(lambda self: u"ipv4")
    def sort_key(self):
        return (0, self.s)

class IPv6Address(Address):
    type = property(lambda self: u"ipv6")
    def sort_key(self):
        return (1, self.s)

class MACAddress(Address):
    type = property(lambda self: u"mac")
    def sort_key(self):
        return (2, self.s)

class Port(object):
    """A single port, consisting of a port specification, a state, and a service
    version. A specification, or "spec," is the 2-tuple (number, protocol). So
    (10, "tcp") corresponds to the port 10/tcp. Port states are strings, or None
    for "unknown"."""
    def __init__(self, spec, state = None):
        self.spec = spec
        self.state = state
        self.service = Service()

    def state_string(self):
        if self.state is None:
            return u"unknown"
        else:
            return unicode(self.state)

    def spec_string(self):
        return u"%d/%s" % self.spec

    def __cmp__(self, other):
        d = cmp(self.spec, other.spec)
        if d != 0:
            return d
        return cmp((self.spec, self.service), (other.spec, other.service))

    def to_dom_fragment(self, document):
        frag = document.createDocumentFragment()
        elem = document.createElement(u"port")
        elem.setAttribute(u"portid", unicode(self.spec[0]))
        elem.setAttribute(u"protocol", self.spec[1])
        if self.state is not None:
            state_elem = document.createElement(u"state")
            state_elem.setAttribute(u"state", self.state)
            elem.appendChild(state_elem)
        elem.appendChild(self.service.to_dom_fragment(document))
        frag.appendChild(elem)
        return frag

class Service(object):
    """A service version as determined by -sV scan. Also contains the looked-up
    port name if -sV wasn't used."""
    def __init__(self):
        self.name = None
        self.product = None
        self.version = None
        self.extrainfo = None
        self.tunnel = None

        # self.hostname = None
        # self.ostype = None
        # self.devicetype = None

    def __eq__(self, other):
        return self.name == other.name \
            and self.product == other.product \
            and self.version == other.version \
            and self.extrainfo == other.extrainfo

    def __ne__(self, other):
        return not self.__eq__(other)

    def name_string(self):
        parts = []
        if self.tunnel is not None:
            parts.append(self.tunnel)
        if self.name is not None:
            parts.append(self.name)

        if len(parts) == 0:
            return None
        else:
            return u"/".join(parts)

    def version_string(self):
        """Get a string like in the VERSION column of Nmap output."""
        parts = []
        if self.product is not None:
            parts.append(self.product)
        if self.version is not None:
            parts.append(self.version)
        if self.extrainfo is not None:
            parts.append(u"(%s)" % self.extrainfo)

        if len(parts) == 0:
            return None
        else:
            return u" ".join(parts)

    def to_dom_fragment(self, document):
        frag = document.createDocumentFragment()
        elem = document.createElement(u"service")
        for attr in (u"name", u"product", u"version", u"extrainfo", u"tunnel"):
            v = getattr(self, attr)
            if v is None:
                continue
            elem.setAttribute(attr, v)
        if len(elem.attributes) > 0:
            frag.appendChild(elem)
        return frag

def format_banner(scan):
    """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like Nmap doeself.versi  """Format a startup banner more or less like 