Nmap Development mailing list archives

[PATCH] Nmap bug determining IP address from network interface name


From: "Luis M." <luis.mgarc () gmail com>
Date: Tue, 07 Jul 2009 14:37:41 +0200

Hi!

Yesterday, Fyodor and I discovered a bug in Nping. For some strange reason
network interface names were being "resolved" to IP 2.0.0.0.

I've looked into it and discovered that the bug also affects nmap
because I've tracked it down to function devname2ipaddr().

So here it goes the explanation:

In file nping.cc, function nmap_main():

  if (o.af() == AF_INET && *o.device && !o.v4sourceip()) {
    struct sockaddr_in tmpsock;
    memset(&tmpsock, 0, sizeof(tmpsock));
    if (devname2ipaddr(o.device, &(tmpsock.sin_addr)) == -1) {
      fatal("I cannot figure out what source address to use for device
%s, does it even exist?", o.device);
    }
    tmpsock.sin_family = AF_INET;
#if HAVE_SOCKADDR_SA_LEN
    tmpsock.sin_len = sizeof(tmpsock);
#endif
    o.setSourceSockAddr((struct sockaddr_storage *) &tmpsock,
sizeof(tmpsock));
  }

Well, if we add the following line:

    printf("This is the IP that we get:
%s.\n",inet_ntoa(tmpsock.sin_addr) );

After compiling, run:

$ sudo nmap -e wlan0 google.com --packet-trace

Starting Nmap 4.85BETA10 ( http://nmap.org ) at 2009-07-07 13:36 CEST
This is the IP that we get: 2.0.0.0.
SENT (0.1100s) ICMP 172.20.68.120 > 74.125.45.100 echo request
(type=8/code=0) ttl=45 id=41477 iplen=28
SENT (0.1100s) TCP 172.20.68.120:35496 > 74.125.45.100:443 S ttl=41
id=19034 iplen=44  seq=1097900095 win=2048 <mss 1460>
[...]

As you can see. The IP address being returned by devname2ipaddr() is
2.0.0.0.
However, that doesn't seem to affect Nmap because, at some point in the
code,
it manages to determine 172.20.68.120 as the propper src address.

So now let's see the problem. This is the code for devname2ipaddr():

int devname2ipaddr(char *dev, struct in_addr *addr) {
struct interface_info *mydevs;
int numdevs;
int i;
mydevs = getinterfaces(&numdevs);

if (!mydevs) return -1;

for(i=0; i < numdevs; i++) {
  if (!strcmp(dev, mydevs[i].devfullname)) {  
    memcpy(addr, (char *) &mydevs[i].addr, sizeof(struct in_addr));
    return 0;
  }
}
return -1;
}

So devname2ipaddr() obtains a list of network interfaces and then tries to
find the one whose name maches param "dev". Well, the problem here is that
in the returned "struct interface_info", member "addr" is of type   
"struct sockaddr_storage", and therefore, the conversion to "struct in_addr"
cannot be done just saying "hey, let's copy &mydevs[i].addr into a
"struct in_addr", because sockaddr_storage contains, at least, a member
named sa_family before the actual address information. So, to sum up,
we are copying data from the wrong memory address (on my Linux box, 4
bytes earlier than we should).

Of course, AF_INET is normally defined as "#define AF_INET 2", and
that's why
we are getting IP 2.0.0.0.

So I attach a patch that solves the problem but I think some of you guys
should check it and test how this change affects Nmap.

Regards,

Luis.






Index: tcpip.cc
===================================================================
--- tcpip.cc    (revision 14088)
+++ tcpip.cc    (working copy)
@@ -2798,6 +2798,7 @@
 
 int devname2ipaddr(char *dev, struct in_addr *addr) {
 struct interface_info *mydevs;
+struct sockaddr_in *s;
 int numdevs;
 int i;
 mydevs = getinterfaces(&numdevs);
@@ -2806,7 +2807,8 @@
 
 for(i=0; i < numdevs; i++) {
   if (!strcmp(dev, mydevs[i].devfullname)) {  
-    memcpy(addr, (char *) &mydevs[i].addr, sizeof(struct in_addr));
+    s=(struct sockaddr_in *)&mydevs[i].addr;
+    memcpy(addr, (char *) &s->sin_addr, sizeof(struct in_addr));
     return 0;
   }
 }

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: