What follows is a comparison of the XML output of Nmap and Zenmap. They are almost the same. Zenmap adds a few attributes to record information about the profile. Zenmap doesn't support all the output that Nmap does.
The purpose of this comparison is to aid the unification of Nmap and Zenmap XML, with the goal of having them both use the same file format. Following the example is an analysis that lays out how this might be done.
Blank lines show where are part of the output was added or removed between the two formats.
| Nmap XML output | Zenmap XML output |
|---|---|
<nmaprun scanner="nmap" args="nmap -A -v -oX router.xml ..." start="..." startstr="..." version="4.68" xmloutputversion="1.02"> |
<nmaprun scanner="nmap"
args="nmap -T Aggressive -A -v ..."
start="..." startstr="..."
version="4.68"
annotation="" description="" hint=""
scan_name=""
options="Aggressive,Version detection,
Verbose,Operating system detection"
profile="nmap -T Aggressive -A -v %s"
profile_name="Intense Scan"
nmap_output="Starting Nmap 4.68...">
|
In the root nmaprun element, Zenmap does not write the xmloutputversion attribute. It adds the following attributes:
description, annotation, hintscan_nameOptionsprofileprofile_editor.xml.
profile_namenmap_output
<scaninfo type="syn" protocol="tcp"
numservices="1715"
services="1-1027,1029-1033..."/>
<verbose level="1"/>
<debugging level="0"/>
|
<scaninfo type="syn" protocol="tcp"
numservices="1715"
services="1-1027,1029-1033..."/>
<verbose level="1"/>
<debugging level="0"/>
|
The scaninfo, verbose, and debugging elements are the same.
<taskbegin time="..."
task="ARP Ping Scan"/>
<taskend time="..."
task="ARP Ping Scan"
extrainfo="1 total hosts"/>
<taskbegin .../>
<taskend .../>
| |
Zenmap doesn't support taskbegin and taskend elements.
<host starttime="..." endtime="..."> | <host comment=""> |
Zenmap doesn't support the starttime and endtime attributes and adds its own comment attribute, which is the comment on the "Host Details" sub-tab.
<status state="up"
reason="arp-response"/>
|
<status state="up"/>
|
Zenmap doesn't support reasons here or anywhere.
<address addrtype="ipv4"
addr="192.168.0.1"/>
<address addrtype="mac"
addr="00:15:05:A2:C7:00"
vendor="Actiontec Electronics"/>
<hostnames>
<hostname name="home.domain"
type="PTR"/>
</hostnames>
<smurf responses="..."/>
|
<address addrtype="ipv4"
addr="192.168.0.1"
vendor=""/>
<address addrtype="" addr=""
vendor=""/>
<address addrtype="mac"
addr="00:15:05:A2:C7:00"
vendor="Actiontec Electronics"/>
<hostnames>
<hostname name="home.domain"
type="PTR"/>
</hostnames>
|
Zenmap inserts a blank address element to hold the nonexistent IPv6 address. It inappropriately adds vendor attributes to the IPv4 and IPv6 address elements. It does not support the smurf element. Although it is not shown here, it also does not support hostscript or trace.
<ports>
<extraports state="closed"
count="1713">
<extrareasons reason="resets"
count="1713"/>
</extraports>
<port protocol="tcp" portid="23">
<state state="open"
reason="syn-ack"
reason_ttl="64"/>
<service name="telnet"
product="BusyBox telnetd"
method="probed" conf="10"/>
</port>
<port protocol="tcp" portid="80">
<state state="open"
reason="syn-ack"
reason_ttl="64"/>
<service name="http"
product="Vonage http config"
devicetype="VoIP adapter"
method="probed" conf="10"/>
<script id="HTML title"
output="Actiontec Firmware"/>
</port>
</ports>
|
<ports>
<extraports state="closed"
count="1713"/>
<port protocol="tcp" portid="23">
<state state="open"/>
<service name="telnet"
product="BusyBox telnetd"
method="probed" conf="10"
version="" extrainfo=""/>
</port>
<port protocol="tcp" portid="80">
<state state="open"/>
<service name="http"
product="Vonage http config"
devicetype="VoIP adapter"
method="probed" conf="10"
version="" extrainfo=""/>
</port>
</ports>
|
Zenmap doesn't have reasons. It inserts vendor and extrainfo attributes even when they are blank. Zenmap doesn't support NSE output (script tag).
There are a number of other attributes of service that Zenmap cannot output: tunnel, proto, rpcnum, lowver, highver, hostname, ostype, devicetype, servicefp.
<os>
<portused state="open"
proto="tcp" portid="23"/>
<portused state="closed"
proto="tcp" portid="1"/>
<portused state="closed"
proto="udp" portid="38153"/>
<osclass type="..." vendor="..."
osfamily="..." accuracy="..."/>
<osclass .../>
<osmatch name="..."
accuracy="100"
line="380"/>
<osfingerprint
fingerprint="OS:SCAN(..."/>
</os>
|
<os>
<portused state="open"
proto="tcp" portid="23"/>
<portused state="closed"
proto="tcp" portid="1"/>
<portused state="closed"
proto="udp" portid="38153"/>
<osclass type="..." vendor="..."
osfamily="..." accuracy="..."
osgen=""/>
<osclass .../>
<osmatch name="..."
accuracy="100"/>
</os>
|
Zenmap inserts blank osgen attributes. It doesn't report the line number of OS matches or record the OS fingerprint.
<uptime seconds="..."
lastboot="..."/>
<distance value="1"/>
<tcpsequence index="203"
difficulty="Good luck!"
values="...,...,..."/>
<ipidsequence class="All zeros"
values="0,0,0,0,0,0"/>
<tcptssequence class="100HZ"
values="...,...,..."/>
<times srtt="6122" rttvar="8687"
to="100000"/>
</host>
|
<uptime seconds="..."
lastboot="..."/>
<tcpsequence index="203"
difficulty="Good luck!"
values="...,...,..."/>
<ipidsequence class="All zeros"
values="0,0,0,0,0,0"/>
<tcptssequence class="100HZ"
values="...,...,..."/>
</host>
|
Zenmap doesn't have the distance element. It doesn't report the times element.
<runstats>
<finished time="..."
timestr="..."/>
<hosts up="1" down="0" total="1"/>
</runstats>
</nmaprun>
|
<runstats>
<finished time="..."/>
<hosts up="1" down="0" total="1"/>
</runstats>
</nmaprun>
|
Zenmap doesn't have the timestr attribute of finished, probably just an oversight.
Apart from the nmap_output attribute and the profile-related attributes in the nmaprun element, Zenmap XML is a subset of Nmap XML. An easy way to make the formats the same would be to extend Nmap XML to include these extra attributes.
A key piece of information is the nmap_output attribute. This is necessary to record Nmap's interactive text output. Without it, yout just see a blank output window (try opening a plain Nmap XML file in Zenmap). This could easily be made into an optional attribute in the Nmap DTD. However, I would prefer to see it made an element rather than an attribute, so it would look like
<nmaprun> <output> Starting Nmap 4.68 ( http://nmap.org ) at 2008-07-17 12:31 MDT Initiating SYN Stealth Scan at 12:31 Scanning localhost (127.0.0.1) [1715 ports] Discovered open port 22/tcp on 127.0.0.1 Discovered open port 6000/tcp on 127.0.0.1 Discovered open port 631/tcp on 127.0.0.1 </output>
instead of the current
<nmaprun nmap_output=" Starting Nmap 4.68 ( http://nmap.org ) at 2008-07-17 12:31 MDT Initiating SYN Stealth Scan at 12:31 Scanning localhost (127.0 .0.1) [1715 ports] Discovered open port 22/tcp on 127.0.0.1 Discovered o pen port 6000/tcp on 127.0.0.1 Discovered open port 631/tcp on 127.0.
The remaining elements are
profile
profile_name
description
annotation
hint
options
target
scan_name
All this information is recorded so Zenmap knows what profile was used, and can recreate a profile from a saved scan, if the profile name isn't already known. The description, annotation, and hint nobody uses anyway. target is fairly benign, although it is redundant with Nmap's args (what do you do if the targets differ?). scan_name is not useful, because it can be derived from profile_name and target, plus it is currently always blank because of a bug in Zenmap.
options is an interesting case. It is supposed to be a list of textual option descriptors, like in ~/.zenmap/scan_profile.usp. Something like "Verbose,Ports to scan" which would map to "-v -p". The problem is that this is not enough to reconstruct the options, because the arguments are not stored anywhere. "Ports to scan" is suppoed to take an argument like "1-100" but that's not in the file. Zenmap loads the command line from the profile attribute anyway, but it means if you try to modify a profile from a saved scan in the profile editor all the arguments will be blank.
profile lists the command line with %s in place of the target. profile_name is the name of the profile, like "Intense scan".
It has been shown that a lot is missing from Zenmap's XML output. This could be the cause of data loss, if someone opened an Nmap XML file in Zenmap and saved it again. Information such a script output and OS and service fingerprints would be gone. Try it: open a plain Nmap XML file in Zenmap. Change a comment on the "Host Details" tab (to convince Zenmap the scan has changed, otherwise it will refuse to save it again). Things like reasons, script output, and fingerprints will be stripped from the file.
The reason Zenmap misses so much output is that it works by reading an Nmap XML file, parsing it into internal data structures, and writing the data structures back out into XML. Zenmap's data structures simply do not reporesent all the information that is possible in Nmap XML.
I do not think the way to remedy this is to expand Zenmap's data structures to include all this information. Zenmap does not need it all. Rather, I propose that Zenmap's save routine build a document tree from the original Nmap XML, augment it with whatever extra information it needs to, and then write it to disk. This way even information not used by Zenmap will remain in the file.
nmap_output attribute with an output element (keeping backward-compatible processing of nmap_output).
profile_name attribute of nmaprun.
comment attribute of host.
options, target, and profile with an Nmap command line parser that would automatically extract the options and target from args.
This last step is the tricky one. However I believe it is the right way to unify the two file formats. Having an Nmap command line parser in Zenmap would bring other benefits, including the ability to create a profile from a command line and the elimination of all the complexity surrounding the peculiar way command-line options are represented. It would enable the Zenmap command line to work the way it should: see Zenmap command line.