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