libnet_build_icmpv4_unreach is horribly broken

Aaron Turner <[email protected]>
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
So I've been trying to craft some icmp port unreachable packets using
libnet 1.1.1 and 1.1.2-rc4, but either I've lost my mind, or
there's some ugly bug hiding somewhere deep in libnet.

Anyways, I've attached a slightly hacked copy of sample/icmp_unreach.c
which illustrates the two errors which occur when you try to send a
series of icmp_unreach's:

1) you can only send 1 packet when using LIBNET_LINK (libnet can't find
the ether header on subsequent calls to libnet_write())

2) when using LIBNET_RAW4, only the first packet is actually sent
(contrary to libnet_write indicating success) AND subseqent calls to
libnet_write() indicates that the packet is growing.  (use -r)

-- 
Aaron Turner <aturner at pobox.com|synfin.net>  http://synfin.net/
They that can give up essential liberty to obtain a little temporary 
safety deserve neither liberty nor safety. -- Benjamin Franklin
All emails are PGP signed; a lack of a signature indicates a forgery.
icmp_unreach.c (text/x-csrc, 6.6 KB)
/*
 *  $Id: icmp_unreach.c,v 1.2 2004/01/03 20:31:01 mike Exp $
 *
 *  libnet 1.1
 *  Build an ICMP unreachable packet
 *
 *  Hacked by Aaron Turner <[email protected]> to illustrate two bugs
 *
 *  Copyright (c) 1998 - 2004 Mike D. Schiffman <[email protected]>
 *  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#if (HAVE_CONFIG_H)
#include "../include/config.h"
#endif
#include "./libnet_test.h"

int
main(int argc, char **argv)
{
    int c, i;
    libnet_t *l = NULL;
    libnet_ptag_t icmp = 0, ip = 0, eth = 0;
    u_long src_ip, dst_ip; 
    u_char payload[8] = {0x11, 0x11, 0x22, 0x22, 0x00, 0x08, 0xc6, 0xa5};
    u_long payload_s = 8;
    int mode = LIBNET_LINK;
    char errbuf[LIBNET_ERRBUF_SIZE];

    printf("libnet 1.1 packet shaping: ICMP unreachable[link]\n"); 

    src_ip = 0;
    dst_ip = 0;

    while((c = getopt(argc, argv, "d:s:r")) != EOF)
    {
        switch (c)
        {
            case 'd':
                if ((dst_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                {
                    fprintf(stderr, "Bad destination IP address: %s\n", optarg);
                    exit(1);
                }
                break;
            case 's':
                if ((src_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                {
                    fprintf(stderr, "Bad source IP address: %s\n", optarg);
                    exit(1);
                }
                break;
            case 'r':
                mode = LIBNET_RAW4;
                break;
        }
    }
    if (!src_ip || !dst_ip)
    {
        usage(argv[0]);
        exit(EXIT_FAILURE);
    }

    /*
     *  Initialize the library.  Root priviledges are required.
     */
    l = libnet_init(
            mode,                            /* injection type */
            NULL,                                   /* network interface */
            errbuf);                                /* errbuf */
 
    if (l == NULL)
    {
        fprintf(stderr, "libnet_init() failed: %s", errbuf);
        exit(EXIT_FAILURE);
    }

for (i = 1; i <= 255; i ++) {
    icmp = libnet_build_icmpv4_unreach(
        ICMP_UNREACH,                               /* type */
        ICMP_UNREACH_PORT,                          /* code */
        0,                                          /* checksum */
            LIBNET_IPV4_H + payload_s,              /* o length */
            IPTOS_LOWDELAY | IPTOS_THROUGHPUT,      /* o IP tos */
            (u_int16_t)i,                           /* o IP ID */
            0,                                      /* o frag */
            64,                                     /* o TTL */
            IPPROTO_UDP,                            /* o protocol */
            0,                                      /* o checksum */
            dst_ip,                                 /* o source IP */
            src_ip,                                 /* o destination IP */
            payload,                                /* payload */
            payload_s,                              /* payload size */
        l,                                          /* libnet handle */
        icmp);
    if (icmp == -1)
    {
        fprintf(stderr, "Can't build ICMP header: %s\n", libnet_geterror(l));
        goto bad;
    }

    ip = libnet_build_ipv4(
        LIBNET_IPV4_H + LIBNET_ICMPV4_UNREACH_H +
        LIBNET_IPV4_H + payload_s,                  /* length */
        IPTOS_LOWDELAY | IPTOS_THROUGHPUT,          /* TOS */
        (u_int16_t)i,                               /* IP ID */
        0,                                          /* IP Frag */
        64,                                         /* TTL */
        IPPROTO_ICMP,                               /* protocol */
        0,                                          /* checksum */
        src_ip,                                     /* source IP */
        dst_ip,                                     /* destination IP */
        NULL,                                       /* payload */
        0,                                          /* payload size */
        l,                                          /* libnet handle */
        ip);
    if (ip == -1)
    {
        fprintf(stderr, "Can't build IP header: %s\n", libnet_geterror(l));
        goto bad;
    }

    if (mode == LIBNET_LINK) {
    eth = libnet_build_ethernet(
       enet_dst,                                   /* ethernet destination */
        enet_src,                                   /* ethernet source */
        ETHERTYPE_IP,                               /* protocol type */
        NULL,                                       /* payload */
        0,                                          /* payload size */
        l,                                          /* libnet handle */
        eth);                                         /* libnet id */

    if (eth == -1)
    {
        fprintf(stderr, "Can't build ethernet header: %s\n", libnet_geterror(l));
        goto bad;
    }
    }
    /*
     *  Write it to the wire.
     */
    c = libnet_write(l);
    if (c == -1)
    {
        fprintf(stderr, "Write error: %s\n", libnet_geterror(l));
        goto bad;
    }
    else
    {
        fprintf(stderr, "Wrote %d byte ICMP packet; check the wire.\n", c);
    }
}
    libnet_destroy(l);
    return (EXIT_SUCCESS);
bad:
    libnet_destroy(l);
    return (EXIT_FAILURE);
}


void
usage(char *name)
{
    fprintf(stderr, "usage: %s [-r] -s source_ip -d destination_ip\n ", name);
}

/* EOF */
signature.asc (application/pgp-signature, 254 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Public key at: http://www.synfin.net/aturner/pgpkey.asc

iD8DBQFAQ9s2hweYF/hu2uYRAu5vAJ9K7Onr05XV4w+4ErMlLkVc/7RLeACfaFfR
T2h6hb4To8/RirBuM8r5T9w=
=NcMa
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.