Created
July 1, 2022 08:17
-
-
Save AtieP/8410348dbc00f21900be856f01905b75 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Prototype of an IP spoofer. */ | |
#include <stdio.h> | |
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <assert.h> | |
#include <netinet/ip.h> | |
#include <netinet/udp.h> | |
#include <string.h> | |
#include <errno.h> | |
#define serrno strerror(errno) | |
// do not rely on this | |
static void | |
ip_compute_checksum(struct ip *iphdr) | |
{ | |
uint16_t *ptr = (uint16_t *) iphdr; | |
uint16_t sum = 0; | |
int carries = 0; | |
for (size_t i = 0; i < sizeof(*iphdr) / sizeof(uint16_t); i++) { | |
if (sum + *ptr < sum) | |
carries++; | |
sum += *ptr++; | |
} | |
sum = ~(sum + carries); | |
iphdr->ip_sum = htons(sum); | |
} | |
// do not rely on this | |
static void | |
udp_compute_checksum(struct udphdr *udphdr, const char *data, size_t data_len) | |
{ | |
uint16_t *ptr = (uint16_t *) udphdr; | |
uint16_t sum = 0; | |
int carries = 0; | |
for (size_t i = 0; i < sizeof(*udphdr) / sizeof(uint16_t); i++) { | |
if (sum + *ptr < sum) | |
carries++; | |
sum += *ptr; | |
} | |
ptr = (uint16_t *) data; | |
for (size_t i = 0; i < data_len / sizeof(uint16_t); i++) { | |
if (sum + *ptr < sum) | |
carries++; | |
sum += *ptr; | |
} | |
sum = ~(sum + carries); | |
udphdr->uh_sum = htons(sum); | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
const char *prog; /* The program name. */ | |
int sockfd; /* The socket file descriptor. */ | |
struct sockaddr_in inaddr; /* Input address. */ | |
struct sockaddr_in outaddr; /* Output address. */ | |
struct ip iphdr; | |
struct udphdr udphdr; | |
struct iovec data[3]; /* One for IP, other for UDP, other for the data. */ | |
struct msghdr msg; | |
inaddr.sin_family = AF_INET; | |
outaddr.sin_family = AF_INET; | |
inaddr.sin_port = 0; | |
outaddr.sin_port = 0; | |
prog = argv[0]; | |
if (argc < 3) { | |
printf("usage: %s <SOURCE> <DESTINATION>\n" | |
"SOURCE and DESTINATION must be IPv4 addresses.\n", | |
prog ? prog : "spoofer"); | |
return 0; | |
} | |
if (inet_pton(AF_INET, argv[1], &inaddr.sin_addr.s_addr) != 1) { | |
fprintf(stderr, "%s: invalid source address\n", prog); | |
return 1; | |
} | |
if (inet_pton(AF_INET, argv[2], &outaddr.sin_addr.s_addr) != 1) { | |
fprintf(stderr, "%s: invalid destination address\n", prog); | |
return 1; | |
} | |
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); | |
if (sockfd < 0) { | |
fprintf(stderr, "%s: socket creation failure: %s\n", prog, serrno); | |
return 1; | |
} | |
char dataz[1500 - sizeof(struct ip) - sizeof(struct udphdr)]; | |
memset(dataz, 0, sizeof(dataz)); | |
strcpy(dataz, "hello world"); | |
/* Cook IP header. */ | |
memset(&iphdr, 0, sizeof(iphdr)); | |
iphdr.ip_hl = sizeof(iphdr) / sizeof(uint32_t); /* Length in DWORDS */ | |
assert(iphdr.ip_hl >= 5); | |
iphdr.ip_v = 4; /* Version */ | |
iphdr.ip_tos = IPTOS_PREC_ROUTINE; /* Type of Service: Routine, Normal Delay */ | |
iphdr.ip_len = htons(sizeof(iphdr) + sizeof(udphdr) + sizeof(dataz)); | |
iphdr.ip_id = htons(0); | |
iphdr.ip_off = htons(IP_DF); /* Do not fragment */ | |
iphdr.ip_ttl = 60; /* Time to live: 60 seconds */ | |
iphdr.ip_p = IPPROTO_UDP; | |
iphdr.ip_src.s_addr = inaddr.sin_addr.s_addr; | |
iphdr.ip_dst.s_addr = outaddr.sin_addr.s_addr; | |
iphdr.ip_sum = 0; | |
//ip_compute_checksum(&iphdr); | |
/* Now the UDP header. */ | |
memset(&udphdr, 0, sizeof(udphdr)); | |
udphdr.uh_sport = htons(5000); | |
udphdr.uh_dport = htons(5000); | |
udphdr.uh_ulen = htons(sizeof(udphdr) + sizeof(dataz)); | |
udphdr.uh_sum = 0; | |
//udp_compute_checksum(&udphdr, argv[3], sizeof(dataz)); | |
/* Send the data. */ | |
memset(&msg, 0, sizeof(msg)); | |
msg.msg_iov = data; | |
msg.msg_iovlen = sizeof(data) / sizeof(struct iovec); | |
data[0].iov_base = &iphdr; | |
data[0].iov_len = sizeof(iphdr); | |
data[1].iov_base = &udphdr; | |
data[1].iov_len = sizeof(udphdr); | |
data[2].iov_base = dataz; | |
data[2].iov_len = sizeof(dataz); | |
msg.msg_name = &outaddr; | |
outaddr.sin_port = htons(5000); | |
msg.msg_namelen = sizeof(outaddr); | |
if (sendmsg(sockfd, &msg, 0) < (ssize_t) (sizeof(iphdr) + sizeof(udphdr) + sizeof(dataz))) { | |
fprintf(stderr, "%s: sendmsg failure: %s\n", prog, strerror(errno)); | |
return 1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment