How to get the IP address from the XML output of nmap with a specific "vendor" using ElementTree in Python

1

Using the nmap XML output for reachable virtual machines running on the same host machine - obtained with nmap -oX output.xml -sP 192.168.2.* , I'd like to get the IP address of each machine whose "vendor" attribute is QEMU Virtual NIC . I chose to use the XML ElementTree API to do it , but I'm having trouble isolating the host elements with the specified address elements.

Here is an excerpt of the XML output to be used:

<host><status state="up" reason="arp-response"/>
<address addr="192.168.2.93" addrtype="ipv4"/>
<address addr="52:54:00:E2:17:31" addrtype="mac" vendor="QEMU Virtual NIC"/>
<hostnames>
</hostnames>
<times srtt="1023" rttvar="5000" to="100000"/>
</host>
<host><status state="up" reason="arp-response"/>
<address addr="192.168.2.96" addrtype="ipv4"/>
<address addr="52:54:00:45:86:8A" addrtype="mac" vendor="QEMU Virtual NIC"/>
<hostnames>
</hostnames>
<times srtt="155" rttvar="5000" to="100000"/>
</host>
<host><status state="up" reason="arp-response"/>
<address addr="192.168.2.103" addrtype="ipv4"/>
<address addr="52:54:00:61:7A:E5" addrtype="mac" vendor="QEMU Virtual NIC"/>
<hostnames>
</hostnames>
<times srtt="391" rttvar="5000" to="100000"/>
</host>

Using the findall command and the XPath syntax below, you could find the elements that have the desired "vendor" attribute:

import xml.etree.ElementTree as ET
tree = ET.parse('output.xml')
tree.findall("./host/address/[@vendor='QEMU Virtual NIC']")

But what I really want are the host elements that contain the address elements found above, so I can find the other sub-elements of type "ipv4" to the same host and thus get its IP address. Can someone help me achieve this using XPath and ElementTree ?

    
asked by anonymous 10.03.2014 / 22:34

2 answers

1

A simpler way to get the desired result would be the following expression, which resulted in of this other response on the site in English. I reproduce it here on the site in Portuguese, as it may be useful for someone who does not speak English:

[i.get('addr') for i in tree.findall(
...     './host/address[@vendor="QEMU Virtual NIC"]/../address[@addrtype="ipv4"]')]
    
10.03.2014 / 23:31
1

There is no direct way to find ancestors through ElementTree , but this question in SOEN shows media get around this, for example:

parent_map = {c:p for p in tree.iter() for c in p}

or (for Python versions that do not support dict comprehension):

parent_map = dict((c, p) for p in tree.getiterator() for c in p)

From here you can find host s from address returned:

[parent_map[x] for x in tree.findall("./host/address/[@vendor='QEMU VirtualNIC']")]

If necessary, you can put the results in set (if the same host can have more than one address that fits in the filter).

    
10.03.2014 / 23:11