def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "ips_or_macs", nargs="*", help=("Display results for specified IP (or networks) or MAC addresses" " (or MAC address regexps)."), ) parser.add_argument("-s", "--sensor") parser.add_argument("-c", "--count", action="store_true") parser.add_argument("-r", "--resolve", action="store_true", help="Resolve MAC manufacturer") args = parser.parse_args() flts = ([], []) # MAC & IP filters for arg in args.ips_or_macs: if arg[:1] in "-!~": neg = True arg = arg[1:] else: neg = False match = MAC_ADDR.search(arg) if match: flts[0].append(db.passive.searchmac(mac=arg, neg=neg)) elif arg.startswith("/") and "/" in arg[1:]: flts[0].append( db.passive.searchmac(mac=utils.str2regexp(arg), neg=neg)) elif "/" in arg: flts[1].append(db.passive.searchnet(arg, neg=neg)) else: flts[1].append(db.passive.searchhost(arg, neg=neg)) if not flts[0]: flts[0].append(db.passive.searchmac()) flt = db.passive.flt_or(*flts[0]) if flts[1]: flt = db.passive.flt_and(flt, db.passive.flt_or(*flts[1])) if args.sensor is not None: flt = db.passive.flt_and(flt, db.passive.searchsensor(args.sensor)) if args.count: print(db.passive.count(flt)) return for rec in db.passive.get(flt, sort=[("addr", 1), ("value", 1), ("source", 1)]): rec["times"] = "s" if rec["count"] > 1 else "" if not rec.get("sensor"): rec["sensor"] = "-" if args.resolve: try: manuf = utils.mac2manuf(rec["value"])[0] except (TypeError, ValueError): pass else: rec["value"] = "%s (%s)" % (rec["value"], manuf) print("%(addr)s at %(value)s on %(sensor)s (%(source)s %(count)s " "time%(times)s, %(firstseen)s - %(lastseen)s)" % rec)
def get_nmap(subdb): """Get records from Nmap & View databases :param str subdb: database to query (must be "scans" or "view") :query str q: query (including limit/skip and sort) :query str f: filter :query str callback: callback to use for JSONP results :query bool ipsasnumbers: to get IP addresses as numbers rather than as strings :query bool datesasstrings: to get dates as strings rather than as timestamps :query str format: "json" (the default) or "ndjson" :status 200: no error :status 400: invalid referer :>jsonarr object: results """ subdb_tool = "view" if subdb == "view" else "scancli" subdb = db.view if subdb == "view" else db.nmap flt_params = get_base(subdb) # PostgreSQL: the query plan if affected by the limit and gives # really poor results. This is a temporary workaround (look for # XXX-WORKAROUND-PGSQL). # result = subdb.get(flt_params.flt, limit=flt_params.limit, # skip=flt_params.skip, sort=flt_params.sortby) result = subdb.get( flt_params.flt, skip=flt_params.skip, sort=flt_params.sortby, fields=flt_params.fields, ) if flt_params.unused: msg = "Option%s not understood: %s" % ( "s" if len(flt_params.unused) > 1 else "", ", ".join(flt_params.unused), ) if flt_params.callback is not None: yield webutils.js_alert("param-unused", "warning", msg) utils.LOGGER.warning(msg) elif flt_params.callback is not None: yield webutils.js_del_alert("param-unused") if config.DEBUG: msg1 = "filter: %r" % subdb.flt2str(flt_params.flt) msg2 = "user: %r" % webutils.get_user() utils.LOGGER.debug(msg1) utils.LOGGER.debug(msg2) if flt_params.callback is not None: yield webutils.js_alert("filter", "info", msg1) yield webutils.js_alert("user", "info", msg2) version_mismatch = {} if flt_params.callback is None: if flt_params.fmt == "json": yield "[\n" else: yield "%s([\n" % flt_params.callback # XXX-WORKAROUND-PGSQL # for rec in result: for i, rec in enumerate(result): for fld in ["_id", "scanid"]: try: del rec[fld] except KeyError: pass if flt_params.ipsasnumbers: rec["addr"] = utils.force_ip2int(rec["addr"]) if not flt_params.datesasstrings: for field in subdb.datetime_fields: _set_datetime_field(subdb, rec, field) for port in rec.get("ports", []): if "screendata" in port: port["screendata"] = utils.encode_b64(port["screendata"]) for script in port.get("scripts", []): if "masscan" in script: try: del script["masscan"]["raw"] except KeyError: pass if not flt_params.ipsasnumbers: if "traces" in rec: for trace in rec["traces"]: trace["hops"].sort(key=lambda x: x["ttl"]) for hop in trace["hops"]: hop["ipaddr"] = utils.force_int2ip(hop["ipaddr"]) addresses = rec.get("addresses", {}).get("mac") if addresses: newaddresses = [] for addr in addresses: manuf = utils.mac2manuf(addr) if manuf and manuf[0]: newaddresses.append({"addr": addr, "manuf": manuf[0]}) else: newaddresses.append({"addr": addr}) rec["addresses"]["mac"] = newaddresses if flt_params.fmt == "ndjson": yield "%s\n" % json.dumps(rec, default=utils.serialize) else: yield "%s\t%s" % ( "" if i == 0 else ",\n", json.dumps(rec, default=utils.serialize), ) check = subdb.cmp_schema_version_host(rec) if check: version_mismatch[check] = version_mismatch.get(check, 0) + 1 # XXX-WORKAROUND-PGSQL if flt_params.limit and i + 1 >= flt_params.limit: break if flt_params.callback is None: if flt_params.fmt == "json": yield "\n]\n" else: yield "\n]);\n" messages = { 1: lambda count: ("%d document%s displayed %s out-of-date. Please run " "the following command: 'ivre %s " "--update-schema;" % ( count, "s" if count > 1 else "", "are" if count > 1 else "is", subdb_tool, )), -1: lambda count: ("%d document%s displayed ha%s been inserted by " "a more recent version of IVRE. Please update " "IVRE!" % (count, "s" if count > 1 else "", "ve" if count > 1 else "s")), } for mismatch, count in version_mismatch.items(): message = messages[mismatch](count) if flt_params.callback is not None: yield webutils.js_alert( "version-mismatch-%d" % ((mismatch + 1) // 2), "warning", message) utils.LOGGER.warning(message)
def _display_xml_host(h, out=sys.stdout): out.write('<host') for k in ["timedout", "timeoutcounter"]: if k in h: out.write(' %s=%s' % (k, saxutils.quoteattr(h[k]))) for k in ["starttime", "endtime"]: if k in h: out.write(' %s=%s' % (k, saxutils.quoteattr(h[k].strftime('%s')))) out.write('>') if 'state' in h: out.write('<status state="%s"' % h['state']) for k in ["reason", "reason_ttl"]: kk = "state_%s" % k if kk in h: out.write(' %s="%s"' % (k, h[kk])) out.write('/>') out.write('\n') if 'addr' in h: out.write('<address addr="%s" addrtype="ipv%d"/>\n' % ( h['addr'], 6 if ':' in h['addr'] else 4, )) for atype, addrs in viewitems(h.get('addresses', {})): for addr in addrs: extra = "" if atype == "mac": manuf = utils.mac2manuf(addr) # if manuf: # if len(manuf) > 1 and manuf[1]: # manuf = manuf[1] # else: # manuf = manuf[0] # extra = ' vendor=%s' % saxutils.quoteattr(manuf[0]) if manuf and manuf[0]: extra = ' vendor=%s' % saxutils.quoteattr(manuf[0]) out.write('<address addr="%s" addrtype="%s"%s/>\n' % (addr, atype, extra)) if 'hostnames' in h: out.write('<hostnames>\n') for hostname in h['hostnames']: out.write('<hostname') for k in ['name', 'type']: if k in hostname: out.write(' %s="%s"' % (k, hostname[k])) out.write('/>\n') out.write('</hostnames>\n') out.write('<ports>') for state, counts in viewitems(h.get('extraports', {})): out.write('<extraports state="%s" count="%d">\n' % (state, counts['total'])) for reason, count in viewitems(counts['reasons']): out.write('<extrareasons reason="%s" count="%d"/>\n' % (reason, count)) out.write('</extraports>\n') for p in h.get('ports', []): if p.get('port') == -1: h['scripts'] = p['scripts'] continue out.write('<port') if 'protocol' in p: out.write(' protocol="%s"' % p['protocol']) if 'port' in p: out.write(' portid="%s"' % p['port']) out.write('><state') for k in ['state', 'reason', 'reason_ttl']: kk = 'state_%s' % k if kk in p: out.write(' %s=%s' % (k, saxutils.quoteattr(str(p[kk])))) out.write('/>') if 'service_name' in p: out.write('<service name="%s"' % p['service_name']) for k in [ 'servicefp', 'product', 'version', 'extrainfo', 'ostype', 'method', 'conf' ]: kk = "service_%s" % k if kk in p: if isinstance(p[kk], basestring): out.write(' %s=%s' % (k, saxutils.quoteattr(p[kk]))) else: out.write(' %s="%s"' % (k, p[kk])) # TODO: CPE out.write('></service>') for s in p.get('scripts', []): _display_xml_script(s, out=out) out.write('</port>\n') out.write('</ports>\n') if 'scripts' in h: out.write('<hostscript>') for s in h['scripts']: _display_xml_script(s, out=out) out.write('</hostscript>') for trace in h.get('traces', []): out.write('<trace') if 'port' in trace: out.write(' port=%s' % (saxutils.quoteattr(str(trace['port'])))) if 'protocol' in trace: out.write(' proto=%s' % (saxutils.quoteattr(trace['protocol']))) out.write('>\n') for hop in sorted(trace.get('hops', []), key=lambda hop: hop['ttl']): out.write('<hop') if 'ttl' in hop: out.write(' ttl=%s' % (saxutils.quoteattr(str(hop['ttl'])))) if 'ipaddr' in hop: out.write(' ipaddr=%s' % (saxutils.quoteattr(hop['ipaddr']))) if 'rtt' in hop: out.write( ' rtt=%s' % (saxutils.quoteattr('%.2f' % hop['rtt'] if isinstance( hop['rtt'], float) else hop['rtt']))) if 'host' in hop: out.write(' host=%s' % (saxutils.quoteattr(hop['host']))) out.write('/>\n') out.write('</trace>\n') out.write('</host>\n')
def get_nmap(subdb): """Get records from Nmap & View databases :param str subdb: database to query (must be "scans" or "view") :query str q: query (including limit/skip and sort) :query str callback: callback to use for JSONP results :query bool ipsasnumbers: to get IP addresses as numbers rather than as strings :query bool datesasstrings: to get dates as strings rather than as timestamps :status 200: no error :status 400: invalid referer :>jsonarr object: results """ subdb_tool = "view" if subdb == 'view' else "scancli" subdb = db.view if subdb == 'view' else db.nmap flt_params = get_nmap_base(subdb) # PostgreSQL: the query plan if affected by the limit and gives # really poor results. This is a temporary workaround (look for # XXX-WORKAROUND-PGSQL). # result = subdb.get(flt_params.flt, limit=flt_params.limit, # skip=flt_params.skip, sort=flt_params.sortby) result = subdb.get(flt_params.flt, skip=flt_params.skip, sort=flt_params.sortby) if flt_params.unused: msg = 'Option%s not understood: %s' % ( 's' if len(flt_params.unused) > 1 else '', ', '.join(flt_params.unused), ) if flt_params.callback is not None: yield webutils.js_alert("param-unused", "warning", msg) utils.LOGGER.warning(msg) elif flt_params.callback is not None: yield webutils.js_del_alert("param-unused") if config.DEBUG: msg1 = "filter: %s" % subdb.flt2str(flt_params.flt) msg2 = "user: %r" % webutils.get_user() utils.LOGGER.debug(msg1) utils.LOGGER.debug(msg2) if flt_params.callback is not None: yield webutils.js_alert("filter", "info", msg1) yield webutils.js_alert("user", "info", msg2) version_mismatch = {} if flt_params.callback is None: yield "[\n" else: yield "%s([\n" % flt_params.callback # XXX-WORKAROUND-PGSQL # for rec in result: for i, rec in enumerate(result): for fld in ['_id', 'scanid']: try: del rec[fld] except KeyError: pass if not flt_params.ipsasnumbers: rec['addr'] = utils.force_int2ip(rec['addr']) for field in ['starttime', 'endtime']: if field in rec: if not flt_params.datesasstrings: rec[field] = int(utils.datetime2timestamp(rec[field])) for port in rec.get('ports', []): if 'screendata' in port: port['screendata'] = utils.encode_b64(port['screendata']) for script in port.get('scripts', []): if "masscan" in script: try: del script['masscan']['raw'] except KeyError: pass if not flt_params.ipsasnumbers: if 'traces' in rec: for trace in rec['traces']: trace['hops'].sort(key=lambda x: x['ttl']) for hop in trace['hops']: hop['ipaddr'] = utils.force_int2ip(hop['ipaddr']) addresses = rec.get('addresses', {}).get('mac') if addresses: newaddresses = [] for addr in addresses: manuf = utils.mac2manuf(addr) if manuf and manuf[0]: newaddresses.append({'addr': addr, 'manuf': manuf[0]}) else: newaddresses.append({'addr': addr}) rec['addresses']['mac'] = newaddresses yield "%s\t%s" % ('' if i == 0 else ',\n', json.dumps(rec, default=utils.serialize)) check = subdb.cmp_schema_version_host(rec) if check: version_mismatch[check] = version_mismatch.get(check, 0) + 1 # XXX-WORKAROUND-PGSQL if i + 1 >= flt_params.limit: break if flt_params.callback is None: yield "\n]\n" else: yield "\n]);\n" messages = { 1: lambda count: ("%d document%s displayed %s out-of-date. Please run " "the following command: 'ivre %s " "--update-schema;" % (count, 's' if count > 1 else '', 'are' if count > 1 else 'is', subdb_tool)), -1: lambda count: ('%d document%s displayed ha%s been inserted by ' 'a more recent version of IVRE. Please update ' 'IVRE!' % (count, 's' if count > 1 else '', 've' if count > 1 else 's')), } for mismatch, count in viewitems(version_mismatch): message = messages[mismatch](count) if flt_params.callback is not None: yield webutils.js_alert( "version-mismatch-%d" % ((mismatch + 1) // 2), "warning", message) utils.LOGGER.warning(message)
def _display_xml_host(host: NmapHost, out: TextIO = sys.stdout) -> None: out.write("<host") for k in ["timedout", "timeoutcounter"]: if k in host: out.write(" %s=%s" % (k, saxutils.quoteattr(host[k]))) for k in ["starttime", "endtime"]: if k in host: out.write(" %s=%s" % (k, saxutils.quoteattr(host[k].strftime("%s")))) out.write(">") if "state" in host: out.write('<status state="%s"' % host["state"]) for k in ["reason", "reason_ttl"]: kk = "state_%s" % k if kk in host: out.write(' %s="%s"' % (k, host[kk])) out.write("/>") out.write("\n") if "addr" in host: out.write('<address addr="%s" addrtype="ipv%d"/>\n' % ( host["addr"], 6 if ":" in host["addr"] else 4, )) for atype, addrs in host.get("addresses", {}).items(): for addr in addrs: extra = "" if atype == "mac": manuf = utils.mac2manuf(addr) # if manuf: # if len(manuf) > 1 and manuf[1]: # manuf = manuf[1] # else: # manuf = manuf[0] # extra = ' vendor=%s' % saxutils.quoteattr(manuf[0]) if manuf and manuf[0]: extra = " vendor=%s" % saxutils.quoteattr(manuf[0]) out.write('<address addr="%s" addrtype="%s"%s/>\n' % (addr, atype, extra)) if "hostnames" in host: out.write("<hostnames>\n") for hostname in host["hostnames"]: out.write("<hostname") for k in ["name", "type"]: if k in hostname: out.write(' %s="%s"' % (k, hostname[k])) out.write("/>\n") out.write("</hostnames>\n") out.write("<ports>") for state, counts in host.get("extraports", {}).items(): out.write('<extraports state="%s" count="%d">\n' % (state, counts["total"])) for reason, count in counts["reasons"].items(): out.write('<extrareasons reason="%s" count="%d"/>\n' % (reason, count)) out.write("</extraports>\n") hostscripts: List[NmapScript] = [] for p in host.get("ports", []): if p.get("port") == -1: hostscripts = p["scripts"] continue out.write("<port") if "protocol" in p: out.write(' protocol="%s"' % p["protocol"]) if "port" in p: out.write(' portid="%s"' % p["port"]) out.write("><state") for k in ["state", "reason", "reason_ttl"]: kk = "state_%s" % k if kk in p: out.write(" %s=%s" % (k, saxutils.quoteattr(str(p[kk])))) out.write("/>") if "service_name" in p: out.write('<service name="%s"' % p["service_name"]) for k in [ "servicefp", "product", "version", "extrainfo", "ostype", "method", "conf", ]: kk = "service_%s" % k if kk in p: if isinstance(p[kk], str): out.write(" %s=%s" % (k, saxutils.quoteattr(p[kk]))) else: out.write(' %s="%s"' % (k, p[kk])) # TODO: CPE out.write("></service>") for s in p.get("scripts", []): _display_xml_script(s, out=out) out.write("</port>\n") out.write("</ports>\n") if hostscripts: out.write("<hostscript>") for s in hostscripts: _display_xml_script(s, out=out) out.write("</hostscript>") for trace in host.get("traces", []): out.write("<trace") if "port" in trace: out.write(" port=%s" % (saxutils.quoteattr(str(trace["port"])))) if "protocol" in trace: out.write(" proto=%s" % (saxutils.quoteattr(trace["protocol"]))) out.write(">\n") for hop in sorted(trace.get("hops", []), key=lambda hop: cast(int, hop["ttl"])): out.write("<hop") if "ttl" in hop: out.write(" ttl=%s" % (saxutils.quoteattr(str(hop["ttl"])))) if "ipaddr" in hop: out.write(" ipaddr=%s" % (saxutils.quoteattr(hop["ipaddr"]))) if "rtt" in hop: out.write( " rtt=%s" % (saxutils.quoteattr("%.2f" % hop["rtt"] if isinstance( hop["rtt"], float) else hop["rtt"]))) if "host" in hop: out.write(" host=%s" % (saxutils.quoteattr(hop["host"]))) out.write("/>\n") out.write("</trace>\n") out.write("</host>\n")
def main(): if USING_ARGPARSE: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('ips_or_macs', nargs='*', help='Display results for specified IP (or ' 'networks) or MAC addresses (or MAC address ' 'regexps).') else: parser = optparse.OptionParser(description=__doc__) parser.parse_args_orig = parser.parse_args def my_parse_args(): res = parser.parse_args_orig() res[0].ensure_value('ips_or_macs', res[1]) return res[0] parser.parse_args = my_parse_args parser.add_argument = parser.add_option parser.add_argument('-s', '--sensor') parser.add_argument('-c', '--count', action="store_true") parser.add_argument('-r', '--resolve', action="store_true", help="Resolve MAC manufacturer") args = parser.parse_args() flts = ([], []) # MAC & IP filters for arg in args.ips_or_macs: if arg[:1] in "-!~": neg = True arg = arg[1:] else: neg = False match = MAC_ADDR.search(arg) if match: flts[0].append(db.passive.searchmac(mac=arg, neg=neg)) elif arg.startswith('/') and '/' in arg[1:]: flts[0].append( db.passive.searchmac(mac=utils.str2regexp(arg), neg=neg)) elif '/' in arg: flts[1].append(db.passive.searchnet(arg, neg=neg)) else: flts[1].append(db.passive.searchhost(arg, neg=neg)) if not flts[0]: flts[0].append(db.passive.searchmac()) flt = db.passive.flt_or(*flts[0]) if flts[1]: flt = db.passive.flt_and(flt, db.passive.flt_or(*flts[1])) if args.sensor is not None: flt = db.passive.flt_and(flt, args.sensor) if args.count: print(db.passive.count(flt)) return for rec in db.passive.get(flt, sort=[('addr', 1), ('value', 1), ('source', 1)]): rec["times"] = "s" if rec["count"] > 1 else "" if not rec.get("sensor"): rec["sensor"] = "-" if args.resolve: try: manuf = utils.mac2manuf(rec['value'])[0] except (TypeError, ValueError): pass else: rec['value'] = '%s (%s)' % (rec['value'], manuf) print("%(addr)s at %(value)s on %(sensor)s (%(source)s %(count)s " "time%(times)s, %(firstseen)s - %(lastseen)s)" % rec)
def displayhost(record, showscripts=True, showtraceroute=True, showos=True, out=sys.stdout): """Displays (on `out`, by default `sys.stdout`) the Nmap scan result contained in `record`. """ line = "Host %s" % utils.force_int2ip(record['addr']) if record.get('hostnames'): line += " (%s)" % '/'.join(x['name'] for x in record['hostnames']) if 'source' in record: line += ' from %s' % record['source'] if record.get('categories'): line += ' (%s)' % ', '.join(record['categories']) if 'state' in record: line += ' (%s' % record['state'] if 'state_reason' in record: line += ': %s' % record['state_reason'] line += ')\n' out.write(line) if 'infos' in record: infos = record['infos'] if 'country_code' in infos or 'country_name' in infos: out.write("\t%s - %s" % (infos.get( 'country_code', '?'), infos.get('country_name', '?'))) if 'city' in infos: out.write(' - %s' % infos['city']) out.write('\n') if 'as_num' in infos or 'as_name' in infos: out.write("\tAS%s - %s\n" % (infos.get('as_num', '?'), infos.get('as_name', '?'))) if 'starttime' in record and 'endtime' in record: out.write("\tscan %s - %s\n" % (record['starttime'], record['endtime'])) for state, counts in viewitems(record.get('extraports', {})): out.write("\t%d ports %s (%s)\n" % (counts["total"], state, ", ".join( "%d %s" % (count, reason) for reason, count in viewitems(counts["reasons"]) if reason != "total"))) ports = record.get('ports', []) ports.sort( key=lambda x: (utils.key_sort_none(x.get('protocol')), x['port'])) for port in ports: if port.get('port') == -1: if 'scripts' in port: record['scripts'] = port['scripts'] continue if 'state_reason' in port: reason = " (%s)" % ', '.join([port['state_reason']] + [ "%s=%s" % (field[13:], value) for field, value in viewitems(port) if field.startswith('state_reason_') ]) else: reason = "" if 'service_name' in port: srv = port['service_name'] if 'service_method' in port: srv += ' (%s)' % port['service_method'] for field in [ 'service_product', 'service_version', 'service_extrainfo', 'service_ostype', 'service_hostname' ]: if field in port: srv += ' %s' % port[field] else: srv = "" out.write("\t%-10s%-8s%-22s%s\n" % ('%s/%d' % (port.get('protocol'), port['port']), port.get('state_state', ''), reason, srv)) if showscripts: out.writelines(_scriptoutput(port)) if showscripts: scripts = _scriptoutput(record) if scripts: out.write('\tHost scripts:\n') out.writelines(scripts) mac_addrs = record.get('addresses', {}).get('mac') if mac_addrs: for addr in mac_addrs: out.write('\tMAC Address: %s' % addr) manuf = utils.mac2manuf(addr) if manuf and manuf[0]: out.write(' (%s)' % manuf[0]) out.write('\n') if showtraceroute and record.get('traces'): for trace in record['traces']: proto = trace['protocol'] if proto in ['tcp', 'udp']: proto += '/%d' % trace['port'] out.write('\tTraceroute (using %s)\n' % proto) hops = trace['hops'] hops.sort(key=lambda hop: hop['ttl']) for hop in hops: out.write('\t\t%3s %15s %7s\n' % ( hop['ttl'], utils.force_int2ip(hop['ipaddr']), hop['rtt'], )) if showos and record.get('os', {}).get('osclass'): osclasses = record['os']['osclass'] maxacc = str(max(int(x['accuracy']) for x in osclasses)) osclasses = [ osclass for osclass in osclasses if osclass['accuracy'] == maxacc ] out.write('\tOS fingerprint\n') for osclass in osclasses: out.write('\t\t%(osfamily)s / %(type)s / %(vendor)s / ' 'accuracy = %(accuracy)s\n' % osclass)
def displayhost(record, showscripts=True, showtraceroute=True, showos=True, out=sys.stdout): """Displays (on `out`, by default `sys.stdout`) the Nmap scan result contained in `record`. """ line = "Host %s" % utils.force_int2ip(record["addr"]) if record.get("hostnames"): line += " (%s)" % "/".join(x["name"] for x in record["hostnames"]) if "source" in record: line += " from %s" % ("/".join(record["source"]) if isinstance( record["source"], list) else record["source"]) if record.get("categories"): line += " (%s)" % ", ".join( cat for cat in record["categories"] if not cat.startswith("_")) if "state" in record: line += " (%s" % record["state"] if "state_reason" in record: line += ": %s" % record["state_reason"] line += ")\n" out.write(line) if "infos" in record: infos = record["infos"] if "country_code" in infos or "country_name" in infos: out.write("\t%s - %s" % (infos.get( "country_code", "?"), infos.get("country_name", "?"))) if "city" in infos: out.write(" - %s" % infos["city"]) out.write("\n") if "as_num" in infos or "as_name" in infos: out.write("\tAS%s - %s\n" % (infos.get("as_num", "?"), infos.get("as_name", "?"))) if "starttime" in record and "endtime" in record: out.write("\tscan %s - %s\n" % (record["starttime"], record["endtime"])) for state, counts in record.get("extraports", {}).items(): out.write("\t%d ports %s (%s)\n" % ( counts["total"], state, ", ".join("%d %s" % (count, reason) for reason, count in counts["reasons"].items() if reason != "total"), )) ports = record.get("ports", []) ports.sort( key=lambda x: (utils.key_sort_none(x.get("protocol")), x["port"])) for port in ports: if port.get("port") == -1: if "scripts" in port: record["scripts"] = port["scripts"] continue if "state_reason" in port: reason = " (%s)" % ", ".join([port["state_reason"]] + [ "%s=%s" % (field[13:], value) for field, value in port.items() if field.startswith("state_reason_") ]) else: reason = "" srv = [] if "service_name" in port: srv.append("") if "service_tunnel" in port: srv.append("%s/%s" % (port["service_name"], port["service_tunnel"])) else: srv.append(port["service_name"]) if "service_method" in port: srv.append("(%s)" % port["service_method"]) for field in [ "service_product", "service_version", "service_extrainfo", "service_ostype", "service_hostname", ]: if field in port: srv.append(port[field]) out.write("\t%-10s%-8s%-22s%s\n" % ( "%s/%d" % (port.get("protocol"), port["port"]), port.get("state_state", ""), reason, " ".join(srv), )) if showscripts: out.writelines(_scriptoutput(port)) if showscripts: scripts = _scriptoutput(record) if scripts: out.write("\tHost scripts:\n") out.writelines(scripts) mac_addrs = record.get("addresses", {}).get("mac") if mac_addrs: for addr in mac_addrs: out.write("\tMAC Address: %s" % addr) manuf = utils.mac2manuf(addr) if manuf and manuf[0]: out.write(" (%s)" % manuf[0]) out.write("\n") if showtraceroute and record.get("traces"): for trace in record["traces"]: proto = trace["protocol"] if proto in ["tcp", "udp"]: proto += "/%d" % trace["port"] out.write("\tTraceroute (using %s)\n" % proto) hops = trace["hops"] hops.sort(key=lambda hop: hop["ttl"]) for hop in hops: out.write("\t\t%3s %15s %7s\n" % ( hop["ttl"], utils.force_int2ip(hop["ipaddr"]), hop["rtt"], )) if showos and record.get("os", {}).get("osclass"): osclasses = record["os"]["osclass"] maxacc = str(max(int(x["accuracy"]) for x in osclasses)) osclasses = [ osclass for osclass in osclasses if osclass["accuracy"] == maxacc ] out.write("\tOS fingerprint\n") for osclass in osclasses: out.write("\t\t%(osfamily)s / %(type)s / %(vendor)s / " "accuracy = %(accuracy)s\n" % osclass)