nmap-to-json.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #!/usr/bin/python3
  2. import json
  3. import sys
  4. from enum import Enum
  5. DEBUG = False
  6. full_output = False
  7. hosts = []
  8. # Describe the port fields
  9. class Port:
  10. port_number = 0
  11. state = ""
  12. protocol = ""
  13. owner = ""
  14. service = ""
  15. sunRPCinfo = ""
  16. version = ""
  17. def __str__(self):
  18. return f"Port {self.port_number} - Version: {self.version}"
  19. def todict(self, full=False):
  20. if full:
  21. return {
  22. "port":self.port_number,
  23. "state":self.state,
  24. "protocol":self.protocol,
  25. "owner":self.owner,
  26. "service":self.service,
  27. "RPCInfo":self.sunRPCinfo,
  28. "version":self.version,
  29. }
  30. return {
  31. "port":self.port_number,
  32. "protocol":self.protocol,
  33. "service":self.service,
  34. "version":self.version,
  35. }
  36. # Class to represent all the host attributes
  37. class Host:
  38. ip = ""
  39. status = ""
  40. hostname = ""
  41. ports = [] # Array of Port() items
  42. def todict(self, full):
  43. return {
  44. "ip":self.ip,
  45. "hostname":self.hostname,
  46. "ports":[port.todict(full) for port in self.ports],
  47. "status":self.status
  48. }
  49. def open_gnmap(filename):
  50. with open(filename, "r") as gnmap:
  51. # split into lines and only take the ones that begin with "Host:"
  52. lines = gnmap.read().strip().split("\n")
  53. lines = [l for l in lines if not l.startswith("#") and l.startswith("Host:")]
  54. return lines
  55. # parse every single line
  56. def parse_line(line):
  57. global hosts
  58. # split line into different fields
  59. fields = line.split("\t")
  60. # parse the different fields
  61. out_host = parse_fields(fields)
  62. merge_hosts(out_host)
  63. def parse_host_field(field):
  64. host = Host()
  65. subfields = field.split(" (")
  66. host.ip = subfields[0]
  67. host.hostname =subfields[1].replace(")", "")
  68. if DEBUG: print(f"DEBUG: parse_host_field::ip={host.ip};hostname={host.hostname}")
  69. return host
  70. def parse_ports_field(host, field):
  71. portlist = field.split("/,")
  72. # loop through the ports and append them to the host
  73. for p in portlist:
  74. port = Port()
  75. portparts = p.split("/")
  76. port.port_number = portparts[0]
  77. port.state = portparts[1]
  78. port.protocol = portparts[2]
  79. port.owner = portparts[3]
  80. port.service = portparts[4]
  81. port.sunRPCinfo = portparts[5]
  82. port.version = portparts[6]
  83. host.ports.append(port)
  84. return host
  85. def parse_status_field(host, field):
  86. host.status = field
  87. return host
  88. # Jumptable for the different fields
  89. field_parser = {
  90. "Host": parse_host_field,
  91. "Ports": parse_ports_field,
  92. "Status": parse_status_field,
  93. }
  94. # if no parser for that type of field is implemented
  95. def not_implemented(host, field_type):
  96. return host
  97. def merge_hosts(host):
  98. global hosts
  99. for ih in hosts:
  100. if ih.ip == host.ip:
  101. ih.ports = host.ports
  102. break
  103. else:
  104. hosts.append(host)
  105. # parsed the different fields, each separeted by a space
  106. def parse_fields(fields):
  107. # create a Host instance
  108. host = Host()
  109. # loop each field that is present
  110. for field in fields:
  111. field_type, field_value = field.split(": ")
  112. if DEBUG: print(f"DEBUG: field_type={field_type}")
  113. if DEBUG: print(f"DEBUG: field_content={field_value}")
  114. # Host Field is the most important one
  115. if field_type == "Host":
  116. host = parse_host_field(field_value)
  117. else:
  118. host = field_parser.get(field_type, not_implemented)(host, field_value)
  119. return host
  120. def hosts_to_json(full_output):
  121. global hosts
  122. out = []
  123. for host in hosts:
  124. out.append(host.todict(full_output))
  125. return out
  126. # check usage
  127. if len(sys.argv) == 1:
  128. print(f"usage: {sys.argv[0]} <scan.gnmap>")
  129. exit(1)
  130. elif len(sys.argv) == 3 and sys.argv[2] == "--full":
  131. full_output = True
  132. # Open the gnmap file
  133. lines = open_gnmap(sys.argv[1])
  134. # parse file
  135. for line in lines:
  136. parse_line(line)
  137. # dump as json
  138. print(json.dumps(hosts_to_json(full_output)))