Re: Code working with LIBNET_RAW4, not with LIBNET_LINK

Karen Pease <[email protected]> Tue, 1 Feb 2005 00:34:46 -0600
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
Just as the libnet code examples only work for hard-coded mac addrs, this code 
only works for the gateway.  For example, lets try to generalize it (I'll cut 
out my actual target ip; it's non-local):

        struct arp_entry arp;
#if 1
        int ret=addr_pton("192.168.0.1",&(arp.arp_pa)); //My gateway
#else
        int ret=addr_pton("AAA.BBB.CCC.DDD",&(arp.arp_pa)); //IP snipped out
#endif
        printf("IP: %d.%d.%d.%d  (%d)\n",((u_int8_t*)(&arp.arp_pa.addr_eth))
[0],((u_int8_t*)(&arp.arp_pa.addr_eth))[1],((u_int8_t*)
(&arp.arp_pa.addr_eth))[2],((u_int8_t*)(&arp.arp_pa.addr_eth))[3],ret);

        arp_t* a=arp_open();
        printf("arp_t: %d\n",a);

        ret=arp_get(a,&arp);
        printf("%d\n",ret);

        arp_close(a);

        for (int i=0; i<6; i++)
            uc.dest_mac[i]=((u_int8_t*)(&arp.arp_ha.addr_eth))[i];

        printf("saddr: %02x.%02x.%02x.%02x.%02x.%02x daddr: %02x.%02x.%02x.
%02x.%02x.
%02x\n",uc.src_mac[0],uc.src_mac[1],uc.src_mac[2],uc.src_mac[3],uc.src_mac[4],uc.src_mac[5],uc.dest_mac[0],uc.dest_mac[1],uc.dest_mac[2],uc.dest_mac[3],uc.dest_mac[4],uc.dest_mac[5]);
        send(&uc,argv[3]);

If we run this code as-is, we get:

IP: 192.168.0.1  (0)
arp_t: 134564104
0
saddr: 00.50.04.6c.e7.30 daddr: 00.20.e0.35.54.40

However, if we change the #if 1 to a #if 0, we get:

IP: AAA.BBB.CCC.DDD  (0)
arp_t: 134564104
-1
saddr: 00.50.04.6c.e7.30 daddr: 00.00.00.00.00.00

As you'll note, arp_get gives an error (by returning -1) and doesn't set the 
hardware address.

 - Karen

On Monday 31 January 2005 12:31 am, Mike Schiffman wrote:
> I mentioned this in last email. You need to use libdnet's route lookup
> and ARP cache query routines. Firewalk does exactly this. Below is the
> relevant function from Firewalk-5.0/src/packet_build.c.
>
> int
> fw_packet_build_probe(struct firepack **fp)
> {
>      arp_t *a;
>      route_t *r;
>      struct arp_entry arp;
>      struct route_entry route;
>
>      /* first build our transport layer header */
>      switch ((*fp)->protocol)
>      {
>          case IPPROTO_UDP:
>              if (fw_packet_build_udp(fp) == -1)
>              {
>                  /* error msg set in fw_packet_build_udp() */
>                  return (-1);
>              }
>              break;
>          case IPPROTO_TCP:
>              if (fw_packet_build_tcp(fp) == -1)
>              {
>                  /* error msg set in fw_packet_build_tcp() */
>                  return (-1);
>              }
>              break;
>          default:
>              sprintf((*fp)->errbuf,
>                      "fw_packet_build_probe(): unknown protocol");
>              return (-1);
>      }
>
>      /* build our IPv4 header */
>      (*fp)->ip = libnet_build_ipv4(
>              (*fp)->packet_size,                 /* packetlength */
>              0,                                  /* IP tos */
>              (*fp)->id,                          /* IP id */
>              0,                                  /* IP frag bits */
>              (*fp)->ttl,                         /* IP time to live */
>              (*fp)->protocol,                    /* transport protocol */
>              0,                                  /* checksum */
>              (*fp)->sin.sin_addr.s_addr,         /* IP source */
>              (*fp)->metric,                      /* IP destination */
>              NULL,                               /* IP payload */
>              0,                                  /* IP payload size */
>              (*fp)->l,                           /* libnet context */
>              0);                                 /* No saved ptag */
>
>      if ((*fp)->ip == -1)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "libnet_build_ipv4()
> %s",
>                  libnet_geterror((*fp)->l));
>          return (-1);
>      }
>
>      /*
>       *  Now we need to get the MAC address of our first hop gateway.
>       *  Dnet to the rescue!  We start by doing a route table lookup
>       *  to determine the IP address we use to get to the
>       *  destination host (the metric).
>       */
>      r = route_open();
>      if (r == NULL)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_open()");
>          route_close(r);
>          return (-1);
>      }
>
>      /* convert the metric address to dnet's native addr_t format */
>      if (addr_aton(libnet_addr2name4((*fp)->metric, 0),
>              &route.route_dst) < 0)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "addr_aton()");
>          route_close(r);
>          return (-1);
>      }
>      /* get the route entry telling us how to reach the metric */
>      if (route_get(r, &route) < 0)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_get()");
>          route_close(r);
>          return (-1);
>      }
>      route_close(r);
>
>      a = arp_open();
>      if (a == NULL)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "arp_open()");
>          return (-1);
>      }
>      /* get the MAC of the first hop gateway */
>      arp.arp_pa = route.route_gw;
>      if (arp_get(a, &arp) < 0)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_get()");
>          arp_close(a);
>          return (-1);
>      }
>      arp_close(a);
>
>      /* build our ethernet header */
>      if (libnet_autobuild_ethernet(
>              (u_char *)&arp.arp_ha.addr_eth,
>              ETHERTYPE_IP,
>              (*fp)->l) == -1)
>      {
>          snprintf((*fp)->errbuf, FW_ERRBUF_SIZE,
>                  "libnet_autobuild_ethernet() %s",
>                  libnet_geterror((*fp)->l));
>          arp_close(a);
>          return (-1);
>      }
>
>      return (1);
> }
>
> On Jan 30, 2005, at 8:27 PM, Karen Pease wrote:
> > A couple weeks ago, I posted here with problems sending packets via
> > LIBNET_LINk when they worked with LIBNET_RAW4.  Last I posted, I
> > thought I
> > had resolved the problem by using the libnet_ethernet_autobuild
> > function;
> > however, it turns out that it was only working in a situation that I
> > previously had working (sending from my home computer to my work
> > computer) (I
> > discovered this shortly after I send my last emaiL); I've tried to
> > work on it
> > on my own, but have had no success in getting packets to arrive the
> > other
> > way.  So, I'm still stuck where I was before.
> >
> > The main problem is mac addrs.  The libnet example code for raw
> > sockets (which
> > I was pointed to before) uses hard coded mac addrs; naturally, as I
> > mentioned
> > before, this means that the code is effectively worthless in real-world
> > applications, since you don't know beforehand what a target machine's
> > mac
> > addr will be.  I can get packets from my home computer to my work
> > computer
> > using mac addr ff.ff.ff.ff.ff.ff; however, the same does not work in
> > reverse.
> > Assumedly this has something to do with my router (I'm behind NAT with
> > port
> > forwarding for the port being sent to).  To send packets from work to
> > home, I
> > need to be able to look up the router's mac addr (in fact, if I hard
> > code it,
> > they make it home just fine).  I previously asked if there was a libnet
> > function to do this for you.  I got no clear response, so I assume the
> > answer
> > is "no".
> >
> > So as not to bother the list any more, I decided to try and look it up
> > myself;
> > to the best of my knowlege, this is done with arp who-has requests.
> > So, I
> > tried sending who-has requests, and set up this nice system to send
> > them out
> > and sniff the results back off the network.  I got no response.
> > Looking in
> > tcpdump, only a small percentage of all machines on the network that
> > issued
> > who-has requests got them answered - at least, so far as I could see in
> > sniffed network traffic.  All of the who-has requests seemed to be
> > structured
> > the same (including mine).  So, I'm not sure what I'm missing.
> >
> > In short, I have to ask: How can I get a remote machine's mac addr to
> > use with
> > libnet?  I'm getting somewhat frustrated here.  :(
> >
> >  - Karen
>
> --
> Mike Schiffman, CISSP
> http://www.packetfactory.net/schiffman
> Doveryay No Proveryay