Skip to content

Instantly share code, notes, and snippets.

@AtieP
Created July 1, 2022 08:17
Show Gist options
  • Save AtieP/8410348dbc00f21900be856f01905b75 to your computer and use it in GitHub Desktop.
Save AtieP/8410348dbc00f21900be856f01905b75 to your computer and use it in GitHub Desktop.
/* 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