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

Asked

Viewed 160 times

1

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

Follows a snippet 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 command findall and the syntax XPath below, it was possible to 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 elements host containing the elements address found above, so that I can find the other sub-elements of type "ipv4" for the same host and thus, get your IP address. Can someone help me get this by using Xpath and Elementtree?

2 answers

1

There’s no direct way to find ancestors through ElementTree, but this question in the SOEN shows ways to 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 there you can find the hosts from the addresses returnees:

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

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

  • Thank you for the reply @mgibsonbr, but in the similar question I asked on the site in English answered me a short time ago with a way in which one can walk "up" in the hierarchy using "." , see: http://stackoverflow.com/a/22312105/1007502

  • @Claudio Hm, ok. I didn’t know for sure how much of Xpath Elementtree support, but if he allows .. then it’s quiet.

  • Yes... it’s my first contact with this in Python so I didn’t even dream it was possible too, but I ended up finding it simpler than parent_map ai, it’s a little "cryptic" no? hehe..

1


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

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.