/* http://members.xoom.com/i0wnu - code copyright by Mixter */ /* nscan.c - 1999 (c) Mixter * compile: gcc -O2 -Wall nscan.c -o nscan * This stuff does, just like binfo-udp, an iquery request, * and a version query, if both succeed, the host will be logged * in a file. Finally got this working, uNF */ #define BINDVULN "ns.vuln" #define STATUSLOG "status.log" #define WAIT_FORK 550000 // wait 1/2 second between forks #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void fchk(FILE *fp); void usage(char *name, char *text); int validip(char *ip); int background(); 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); void dns_scan(char *ip); int main(int argc,char **argv) { FILE *data, *err; char ip[30]; int pid; if((argc!=2)) usage(argv[0],""); fprintf(stderr,"lamerz scan 1.0 by Mixter\n"); fprintf(stderr,"scanning from %s (pid: %d)\n" ,argv[1] ,(pid=background())); signal(SIGHUP,SIG_IGN); signal(SIGCHLD,SIG_IGN); // zombies suck fchk(data=fopen(argv[1],"r")); fchk(err=fopen(STATUSLOG,"a")); fprintf(err,"Started DNS scan. File: %s, PID: %d\n",argv[1],pid); while(!feof(data)) { fscanf(data,"%s\n",ip); if(validip(ip)==1) { usleep(WAIT_FORK); // wait between fork()'s (1/2 second default) if ((pid=vfork()) < 0) { perror("fork"); exit(1); } if (pid==0) // child { dns_scan(ip); // collect data for this host & save into files kill(getpid(),9); return 0; } } else fprintf(err,"Invalid IP: %s\n",ip); } sleep(60); // wait for the last childs fprintf(err,"Finished DNS scan. File: %s\n",argv[1]); return 0; } void fchk(FILE *fp) { if(fp==NULL) { fprintf(stderr,"Error opening file or socket.\n"); exit(EXIT_FAILURE); } return; } void usage(char *name,char *text) { printf("usage: %s %s\n",name,text); exit(EXIT_FAILURE); } int validip(char *ip) { int a,b,c,d,*x; sscanf(ip,"%d.%d.%d.%d",&a,&b,&c,&d); x=&a; if(*x < 0) return 0; if(*x > 255) return 0; x=&b; if(*x < 0) return 0; if(*x > 255) return 0; x=&c; if(*x < 0) return 0; if(*x > 255) return 0; x=&d; if(*x < 0) return 0; if(*x > 255) return 0; sprintf(ip,"%d.%d.%d.%d",a,b,c,d); // truncate possible garbage data return 1; } int background() { int pid; signal(SIGCHLD,SIG_IGN); pid = fork(); if(pid<0) return -1; // fork failed if(pid>0) { sleep(1); exit(EXIT_SUCCESS); // parent, exit } if(pid==0) { signal(SIGCHLD,SIG_DFL); return getpid(); // child, go on } return -2; } void dns_scan(char *ip) // this is now 99% binfo rip, duh :/ { struct sockaddr_in xx; xx.sin_family = AF_INET; xx.sin_port = htons (53); xx.sin_addr.s_addr = inet_addr (ip); srand (time (NULL)); probe_bind(xx); return; } 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)) 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); print_ver (rname, dh->rcode == 0, vquery); } int talk (sd, pkt, pktl, opc) int sd, pktl; char *pkt, opc; { int pktlen; pktlen = make_keypkt (pkt, opc); if (!write (sd, pkt, pktlen)) { close(sd); return 0; } signal (SIGALRM, handle_alarm); alarm (3); pktlen = read (sd, pkt, pktl); if (pktlen <= 0) { close(sd); return 0; } alarm (0); return 1; } int make_keypkt (pktbuf, opc) char *pktbuf; char opc; { HEADER *dnsh; char *ptr = pktbuf; int pktlen = 0; dnsh = (HEADER *) ptr; dnsh->id = htons (rand () % 65535); dnsh->opcode = opc; dnsh->rd = 1; dnsh->ra = 1; if (opc == IQUERY) dnsh->ancount = htons (1); else if (opc == QUERY) dnsh->qdcount = htons (1); pktlen += sizeof (HEADER); ptr += sizeof (HEADER); if (opc == QUERY) { 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; } 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); } return pktlen; } void print_ver (host, vul, buf) char *host, *buf; int vul; { HEADER *dnsh = (HEADER *) buf; char *ptr, *verstr; int len; FILE *lamer; if (vul==0) return; if (dnsh->rcode != 0) return; ptr = (buf + sizeof (HEADER)); while (*ptr != '\0') ptr++; ptr += 1 + (sizeof (short) * 2); while (*ptr != '\0') ptr++; ptr += 1 + (sizeof (long) + (sizeof (short) * 2)); GETSHORT (len, ptr); ptr++; verstr = (char *) malloc (len); memset (verstr, 0, len); memcpy (verstr, ptr, len - 1); for (ptr = verstr; ptr - verstr != len - 1; ptr++) if (!isprint (*ptr) && !isspace (*ptr)) *ptr = '.'; fchk(lamer=fopen(BINDVULN,"a")); fprintf(lamer,"%s - %s\n", host, verstr); fclose(lamer); return; } void handle_alarm (signum) int signum; { alarm (0); signal (SIGALRM, SIG_DFL); }