Update! Just talked to the client and he found the following code in: /dev/.cas/ It was named binfo.c I'm willing to bet that this may have something to do with the thrashing on A as well as on various nameservers around the net. int main (int argc, char *argv[]) { if (argc < 2) return 0; checknamed(argv[1]); } /* * This code was written by: * Joshua James Drake (jdrake@pulsar.net) * * Published 6/9/98 @ 12:02 AM * * The following lines of code are, in a nutshell, written to pry * some information from a nameserver. The information it gives * you may or may not be useful. That is for you to decide. * * However, it will tell you if the server supports IQUERY and, if * possible, what version of bind (by Paul Vixie) it is running. * */ /* local type includes */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <string.h> #include <ctype.h> #include <sys/errno.h> /* network type includes */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> #include <netdb.h> /* added the versions i know to be vulnerable. Turned it into a function for * my new scanner. It doesn't return anything, just a printf =) */ /* bulky shit for printing dnspkts need to link dnspkt.o from dnspkt.c too */ #ifdef DEBUG #include "dnspkt.h" #endif /* prototypes */ int lookup_host(struct sockaddr_in *ra, char *hn, unsigned short rp); void probe_bind(struct sockaddr_in ra); int talk(int sd, char *pkt, int pktl, char opc); int make_keypkt(char *pktbuf, char opc); void print_ver(char *host, int vul, char *buf); void handle_alarm(int signum); /* * here we simply check arguments, resolve the hostname given and * if all is well, initialize the radom seed and probe away. */ void checknamed(char *ip) { struct sockaddr_in ra; if (!lookup_host(&ra, ip, NAMESERVER_PORT)) return; srand(time(NULL)); probe_bind(ra); } /* * resolve a hostname to a sockaddr_in struct. * we first try treating it like an ip address in a.b.c.d notation * then, if that fails, we try to resolve using DNS ways * if all fails, we return 0. (failed) * if we get the sockaddr_in struct all filled out, we return 1. */ int lookup_host(ra, hn, rp) struct sockaddr_in *ra; char *hn; unsigned short rp; { struct hostent *he; ra->sin_family = AF_INET; ra->sin_port = htons(rp); if ((ra->sin_addr.s_addr = inet_addr(hn)) != -1) return 1; if ((he = gethostbyname(hn)) != (struct hostent *)NULL) { memcpy(&ra->sin_addr.s_addr, he->h_addr, 4); return 1; } herror("Unable to resolve hostname"); return 0; } /* * here we allocate some space for our packets and make sure it's * "fullanull". then we attempt to allocate and setup our socket. * if failure occurs, we shall report error and return. * the we attempt to reverse our address in the sockaddr_in structure * passed as the only argument into a dns name, if that fails, we go * with the ascii ip address representation. then we attempt to * communicate the remote server, if failure, we return. after we * have successfully got our packets back, we close the socket and * print out a summary of what we got. */ void probe_bind(ra) struct sockaddr_in ra; { int sd; char iquery[512], vquery[512], rname[256]; struct hostent *he; HEADER *dh = (HEADER *)iquery; memset(vquery, 0, sizeof(vquery)); memset(iquery, 0, sizeof(iquery)); if (((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) || (connect(sd, (struct sockaddr *)&ra, sizeof(ra)) == -1)) { perror("Unable to connect"); if (sd != -1) close(sd); return; } // if ((he = gethostbyaddr((char *)&ra.sin_addr, sizeof(ra.sin_addr), //AF_INET)) == (struct hostent *)NULL) sprintf(rname, "%s", inet_ntoa(ra.sin_addr)); // else // strncpy(rname, he->h_name, sizeof(rname)); if (!talk(sd, iquery, sizeof(iquery), IQUERY)) return; if (!talk(sd, vquery, sizeof(vquery), QUERY)) return; close(sd); /* if dh->rcode == 0, then our iquery request was answered and the remote server supports iquery */ print_ver(rname, dh->rcode == 0, vquery); } /* * write our packet from pkt, wait for a response and put it in pkt. * if the alarm goes off or the read fails, we print error * and return 0. otherwise, our response packet is in pkt and we return 1. */ int talk(sd, pkt, pktl, opc) int sd, pktl; char *pkt, opc; { int pktlen; pktlen = make_keypkt(pkt, opc); if (!write(sd, pkt, pktlen)) { perror("write failed"); close(sd); return 0; } #ifdef DEBUG printf("write() success\n"); #endif siginterrupt(SIGALRM, 1); signal(SIGALRM, handle_alarm); alarm(3); pktlen = read(sd, pkt, pktl); if (pktlen <= 0) { if (errno == EINTR) errno = ETIMEDOUT; //perror("read failed"); close(sd); return 0; } #ifdef DEBUG printf("read success\n"); #endif alarm(0); return 1; } /* * this forms a valid dns packet based on the op code given by opc. * only two opcodes are supported because that's all we need to support. * the packet ends up in pktbuf and the length of the packet is returned. */ int make_keypkt(pktbuf, opc) char *pktbuf; char opc; { HEADER *dnsh; char *ptr = pktbuf; int pktlen = 0; dnsh = (HEADER *) ptr; /* fill out the parts of the DNS header that aren't 0 */ dnsh->id = htons(rand() % 65535); dnsh->opcode = opc; dnsh->rd = 1; dnsh->ra = 1; /* one answer for IQUERY, one question for QUERY */ if (opc == IQUERY) dnsh->ancount = htons(1); else if (opc == QUERY) dnsh->qdcount = htons(1); pktlen += sizeof(HEADER); ptr += sizeof(HEADER); /* we have to make a QUERY, fill out the question section */ if (opc == QUERY) { /* version.bind. == elite */ char qstr[] = "\007version\004bind\000"; int qlen = strlen(qstr) + 1; memcpy(ptr, qstr, qlen); ptr += qlen; pktlen += qlen; PUTSHORT(T_TXT, ptr); PUTSHORT(C_CHAOS, ptr); pktlen += sizeof(short) * 2; } /* add a resource record for the inverse query */ else if (opc == IQUERY) { unsigned long addr = inet_addr("1.2.3.4"); unsigned long ttl = 31337; unsigned short addrlen = 4; *(ptr++) = '\0'; pktlen++; PUTSHORT(T_A, ptr); PUTSHORT(C_IN, ptr); PUTLONG(ttl, ptr); PUTSHORT(addrlen, ptr); PUTLONG(addr, ptr); pktlen += (sizeof(short) * 3) + (sizeof(long) * 2); } /* if we're debugging, show what we just made */ #ifdef DEBUG print_dnspkt(pktbuf, pktbuf + pktlen); #endif return pktlen; } /* * This function takes a DNS packet in buf, and whether or not it reponds to IQUERY in vul. * We cast the packet and extract the response as long as there is one. * If there isn't one, then we assume that the remote server is an old version of bind. * this is the end of the line. */ void print_ver(host, vul, buf) char *host, *buf; int vul; { HEADER *dnsh = (HEADER *)buf; char *ptr, *verstr, temp1[256]; int len; /* So we actually have a response. Lets skip the crap, starting with the header */ ptr = (buf + sizeof(HEADER)); /* then the question section domain name. */ while (*ptr != '\0') ptr++; /* then the trailing null and the type/class of the question */ ptr += 1 + (sizeof(short) * 2); /* now we skip the answer section domain name. (should be the same as the question) */ while (*ptr != '\0') ptr++; /* don't forget the trailing null, type, class, and time to live. */ ptr += 1 + (sizeof(long) + (sizeof(short) * 2)); /* Here we are at the resource record data length, extract it */ GETSHORT(len, ptr); /* avoid the need to decompress the string (treat it as one) */ ptr++; /* allocate space for and copy the version response txt */ verstr = (char *)malloc(len); memset(verstr, 0, len); memcpy(verstr, ptr, len-1); /* run through the vesion string and replace non-printable and non-whitespace characters with a '.' */ for (ptr = verstr; ptr - verstr != len - 1; ptr++) if (!isprint(*ptr) && !isspace(*ptr)) *ptr = '.'; /* print the version and iquery support status, woo hoo */ if(vul) { if(strstr(verstr, "8.2") && strstr(verstr, "-") == NULL && strstr(verstr, "-REL") == NULL) printf("%s: VULN: box running bind %s\n",host,verstr); } if(!vul) { if(strstr(verstr, "8.2")&& strstr(verstr, "-") == NULL && strstr(verstr, "-REL") == NULL) printf("%s: VULN: box running bind %s\n",host,verstr); } } /* * handle the alarm signal by resetting the alarm timer and * the signal handler for SIGALRM. This stuff probably isn't needed, * but I did it anyway. It's good for debugging, ran into some problems with * alarm() not doing its job. */ void handle_alarm(signum) int signum; { alarm(0); signal(SIGALRM, SIG_DFL); #ifdef DEBUG printf("recieved alarm\n"); #endif } --- John Fraizer EnterZone, Inc