/*
	______            _  _   __            _ 
	| ___ \          | || | / /           | |
	| |_/ /  ___   __| || |/ /   ___    __| |
	|    /  / _ \ / _` ||    \  / _ \  / _` |
	| |\ \ |  __/| (_| || |\  \| (_) || (_| |
	\_| \_| \___| \__,_|\_| \_/ \___/  \__,_|
                                          
      Icmp Packets Forger for WinNT Systems (2k, XP)

                    - Version 0.1 -
                                      RedKod Team
                                    www.redkod.com
Coder: R-e-D
Mail : r-e-d@redkod.com

*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <winsock2.h>

typedef struct icmp_hdr
{
 unsigned char icmp_type;
 unsigned char icmp_code;
 unsigned short int icmp_cksum; 
 unsigned short int icmp_id;
 unsigned short int icmp_seq;
} ICMP_HDR; 
	

typedef struct ip_hdr
{
    unsigned char  ip_verlen;        
    unsigned char  ip_tos;           
    unsigned short ip_tot_len;       
    unsigned short ip_id;            
    unsigned short ip_offset;        
    unsigned char  ip_ttl;           
    unsigned char  ip_protocol;      
    unsigned short ip_checksum;      
    unsigned int   ip_saddr;         
    unsigned int   ip_daddr;     
} IP_HDR;


typedef struct tmp_hdr
{
      unsigned int saddr;
      unsigned int daddr;
      unsigned char placeholder;
      unsigned char protocol;
      unsigned short icmp_length;
      struct icmp_hdr icmp;
} TMP_HDR;

USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum=0;
    while (size > 1)
    {
        cksum += *buffer++;
        size  -= sizeof(USHORT);   
    }
    if (size)
    {
        cksum += *(UCHAR*)buffer;   
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16); 
    return (USHORT)(~cksum); 
}

int packet_build(unsigned long saddr, unsigned long daddr, unsigned int icmp_type, unsigned int icmp_code, char packet[])
{
    int srcport=0;
    IP_HDR         ip;
    ICMP_HDR	   icmp;
    TMP_HDR	   temp_header;
    unsigned short packet_size, ip_version, ip_len;    
    char	   *ptr = NULL;

    packet_size = sizeof(ip) + sizeof(icmp);
    ip_version = 4;
    ip_len = sizeof(ip) / sizeof(unsigned long);

    ip.ip_verlen   = (ip_version << 4) | ip_len;
    ip.ip_tos      = 0;                         
    ip.ip_tot_len  = htons(packet_size); 
    ip.ip_id       = 1;                
    ip.ip_offset   = 0;             
    ip.ip_ttl      = 128;              
    ip.ip_protocol = IPPROTO_ICMP;
    ip.ip_checksum = 0 ;         
    ip.ip_saddr    = saddr;	
    ip.ip_daddr    = daddr;	

    icmp.icmp_type   = icmp_type;
    icmp.icmp_code   = icmp_code;
    icmp.icmp_cksum  = 0;
    icmp.icmp_id     = 1337;
    icmp.icmp_seq    = 1337;
    
    temp_header.saddr       = saddr;
    temp_header.daddr       = daddr;
    temp_header.placeholder = 0;
    temp_header.protocol    = IPPROTO_ICMP;
    temp_header.icmp_length = htons(sizeof(icmp));
    
    memcpy(&temp_header.icmp,&icmp, sizeof(icmp));

    icmp.icmp_cksum = checksum((unsigned short *)&temp_header, sizeof(temp_header));
    
    ZeroMemory(packet, sizeof(packet));
    ptr = packet;	
    memcpy(ptr, &ip, sizeof(ip));
    ptr += sizeof(ip);
    memcpy(ptr, &icmp, sizeof(icmp));
    ptr += sizeof(icmp);	

    return(0);
}	


int InitWinsock(void)
{
    WSADATA wsaData;

	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    {
	    fprintf(stderr, "WSAStartup() failed: %d\n", GetLastError());
	    exit(-1);
    }

	return(0);
}

SOCKET Create_Raw_Socket(void) 
{
   int sock;
   BOOL  optval = true;
   
   sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0,0);
   if (sock == INVALID_SOCKET)
   {
      fprintf(stderr, "WSASocket() failed: %d\n", WSAGetLastError());
      exit(-1);
   }

    
   if (setsockopt(sock, IPPROTO_IP, 2, (char *)&optval, sizeof(optval)) == SOCKET_ERROR)
   {
	    fprintf(stderr, "setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
	    exit(-1);
   }

   return(sock);
}

int packet_send(char *saddr, char *daddr, unsigned int icmp_type, unsigned int icmp_code, int nbpackets, unsigned int interval)
{
	SOCKET  sock;
	int    ret, i=0, random=0, ip1=0, ip2=0, ip3=0, ip4=0;
	hostent *she, *dhe;
   	struct sockaddr_in shost, dhost;        
   	char packet[40];

	srand((unsigned) time(NULL));

    	InitWinsock();
	sock = Create_Raw_Socket();

	if(!strcmp(saddr, "0")) 	
		random = 1;
	   
	memset(packet, 0, sizeof(packet));
	
	for(i=0; i < nbpackets; i++) 
	{		
		if(random == 1) {			
			ip1 = (rand() % 255) + 1;
			ip2 = (rand() % 255) + 1;
			ip3 = (rand() % 255) + 1;
			ip4 = (rand() % 255) + 1;	
			sprintf(saddr, "%i.%i.%i.%i", ip1, ip2, ip3, ip4);
       		 }

		dhost.sin_family = AF_INET;
			
		she = gethostbyname(saddr);
		if(she == 0)
		{		
			fprintf(stderr, "Error: source address is NULL.\n");
			return(-1);
		}
		memcpy(&shost.sin_addr.s_addr, she->h_addr, 4);
			
		dhe = gethostbyname(daddr);
		if(!dhe) 
		{
			fprintf(stderr, "Error: destination address has not been resolve.\n");
			return(-1);
		}
		memcpy(&dhost.sin_addr.s_addr, dhe->h_addr, 4);
		
		packet_build(shost.sin_addr.s_addr, dhost.sin_addr.s_addr, icmp_type, icmp_code, packet);

		ret = sendto(sock, packet, sizeof(packet), 0, (SOCKADDR *)&dhost, sizeof(dhost));
			
		if (ret == SOCKET_ERROR)   
		{
			fprintf(stderr, "sendto() failed: %d\n", WSAGetLastError());				
			return(-1);
		}
			
		Sleep(interval);
               	fprintf(stdout, ".");	
	}    


    fprintf(stdout, "\nFinish ! Wait close the sock...\n");
    Sleep(2000);
    
    closesocket(sock);
    WSACleanup();

    return(0);
}


int main(int argc, char **argv)
{    
    char *saddr, *daddr;
    int nbpackets=1, interval=0, icmp_type=8, icmp_code=0;
    char *version = "\n    Icmp Packets Forger 0.1\n"
	            "    For NT System By R-e-D\n\n"
		    "    http://www.redkod.com/\n"
		    "      r-e-d@redkod.com\n"
	            "  Save the raw packet mode :)\n\n";  
	

    fprintf(stdout, version);
    if(argc < 7)
    {
	fprintf(stdout, "usage: %s [source address] [destination address] [icmp type] [icmp code] [packets count] [interval (ms)]\n", argv[0]);
	fprintf(stdout, "if source address equal 0, random addresses will be used.\n");
	exit(-1);
    } 
    
    icmp_type = atoi(argv[3]);
    icmp_code = atoi(argv[4]);
    nbpackets = atoi(argv[5]);
    interval  = atoi(argv[6]);

    if(strlen(argv[1]) < 3)
	 saddr = (char *)malloc(4 * sizeof(char *));
    else		    
    saddr = (char *)malloc(strlen(argv[1]) + 1);
   
    daddr = (char *)malloc(strlen(argv[2]) + 1);

    strcpy(saddr, argv[1]);
    strcpy(daddr, argv[2]);
    
    fprintf(stdout, "Source IP      : %s\n", saddr);    
    fprintf(stdout, "Destination IP : %s\n", daddr);
    fprintf(stdout, "ICMP Type      : %d\n", icmp_type);
    fprintf(stdout, "ICMP Code      : %d\n", icmp_code);
    fprintf(stdout, "Packets count  : %d\n", nbpackets);
    fprintf(stdout, "Interval       : %d\n", interval);

    printf("\nStart now !\n");
    packet_send(saddr, daddr, icmp_type, icmp_code, nbpackets, interval);  

    free(daddr);
    free(saddr);
    
    return(0);
}
