Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

v22i049: crack - The Password Cracker, version 3.2a, Part01/04

23 views
Skip to first unread message

Alec David Muffett

unread,
Aug 23, 1991, 11:03:56 AM8/23/91
to
Submitted-by: Alec David Muffett <a...@aber.ac.uk>
Posting-number: Volume 22, Issue 49
Archive-name: crack/part01
Environment: UNIX

This is Crack, v3.2a+fcrypt() : A sensible password cracker for Unix.

[ *PLEASE NOTE*:
[
[ There was an incredibly small bug in the version recently posted to
[ alt.{sources,security}. If you are using that version, please either
[ use this version or apply the fix yourself.
[
[ * Around line 633 of Sources/crack-pwc.c, there is a line which read:-
[ if (!TryManyUsers (head, scratch))
[ and this was changed to :-
[ if (!TryManyUsers (head, scratch->word))
[ ^^^^^^^^^^^^^
[ for Crack to function properly. If you are reading this, it is fixed
[ in this distribution.

The intent of this program is twofold :-

1) To inform the average system manager, in a simple, fast, and easy to
use manner, of those passwords which would be easily compromised by a
dictionary search.

2) To weaken the complacency which develops amongst many inexperienced
(and some experienced) Unix systems people. Just because crypt/DES
cannot (?) be reversed does not mean that user passwords are safe. If
this program serves to raise the overall quotient of paranoia just
little a bit, it is all to the good in my opinion. 8-)

Crack+fcrypt() works on Ultrix and SunOS, and probably on a lot of other
things too. AIX has problems with creating a crypt compatible fcrypt().
For a list of the current problems, see the BUGS file. At worst, just
run with the version of 'crypt()' which comes with your system.

Documentation provided is in the "README" file, which I've handhacked
down to a unutterably boring text file. The "README.ms" file in "Docs"
generates a far prettier output using "nroff -ms", and "Docs/README.ps"
is even prettier still. I suggest that you start by reading one of
these files.

To install: Just create a directory to keep it all in, move the shar
files into the directory, and unshar them.

The most patently obvious difference from the last release is that I
have provided two versions of the driver script "Crack" - one in 'csh'
and one in 'sh'. If the 'sh' one works out okay, I'll eventually trash
the 'csh' version.

Crack will also be archived at:- wuarchive.wustl.edu [128.252.135.4]
in the directory ~/packages.

If you have problems, let me know, so long as they're not too personal.

- Alec 8-)

INET: a...@aber.ac.uk JANET: a...@uk.ac.aber BITNET: aem%aber@ukacrl
UUCP: ...!mcsun!ukc!aber!aem ARPA: aem%uk.ac...@nsfnet-relay.ac.uk
SNAIL: Alec Muffett, Computer Unit, Llandinam UCW, Aberystwyth, UK, SY23 3DB
----------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 4)."
# Contents: BUGS Crack.sh DictSrc Dicts Docs MANIFEST README
# README.FIRST Scripts Scripts/Crack.network Scripts/RCrack
# Scripts/clean Scripts/crack.mf Scripts/install.mf
# Scripts/joinfiles Scripts/makedicts Scripts/network.conf
# Scripts/network.conf.example Scripts/plaster Scripts/spotless
# Sources Sources/Makefile Sources/conf.h Sources/crack-lib.c
# Sources/crack-port.c Sources/crack.h Sources/speeds.c
# Sources/tester.c
# Wrapped by aem@aberda on Fri Aug 23 13:20:39 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'BUGS' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'BUGS'\"
else
echo shar: Extracting \"'BUGS'\" \(1757 characters\)
sed "s/^X//" >'BUGS' <<'END_OF_FILE'
XKnown bugs as of Aug 23, 1991.
X
X* One version of Crack 3.2 has gotten away from me with the
X DEVELOPMENT_VERSION symbol #defined. This is OK if you are on a
X DEC Risc-Ultrix box, but probably not otherwise. Doublecheck this.
X If you are reading this message, you should be OK.
X
X* GCC : Doesn't seem to want to compile fcrypt() so that it is
X compatible with crypt(). Use your stock CC. If this doesn't work,
X "#undef CRYPT" in "Sources/conf.h" and run without fcrypt().
X
X If you can follow the fcrypt() code, let me know what GCC doesn't
X like. Otherwise, just tell me about it.
X
X* AIX : Doesn't like the -O2 flag, which is survivable on most versions
X of Unix. It's just a switch to turn on optimisation and so may be
X safely removed.
X
X* AIX : Didn't like putting static data items > 256 in a u_char. I have
X fixed the array in question (I think).
X
X* AIX : After all this, fcrypt() apparently does not come out of the AIX
X CC compiler compatible with crypt(). If you really have no idea why
X it does not work, "#undef FCRYPT" in "Sources/conf.h" and proceed as
X normal.
X
X* AWK : Someone at Nottingham complained that "RCrack" fell over when he
X ran it, because he was using version 2 of "awk". I'm not sure whether
X he meant "nawk" by this, but he said that it was fixed by editing
X "RCrack" and invoking "/bin/awk" literally. This MAY also affect
X "joinfiles" and "Crack.network".
X
X* There was a major bug in v3.2 crack-pwc.c which I have fixed. Around
X line 633 of Sources/crack-pwc.c, there is a line which read:-
X
X if (!TryManyUsers (head, scratch))
X
X and this was changed to :-
X
X if (!TryManyUsers (head, scratch->word))
X
X for Crack to function properly. If you are reading this, it is fixed
X in this distribution.
END_OF_FILE
if test 1757 -ne `wc -c <'BUGS'`; then
echo shar: \"'BUGS'\" unpacked with wrong size!
fi
# end of 'BUGS'
fi
if test -f 'Crack.sh' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Crack.sh'\"
else
echo shar: Extracting \"'Crack.sh'\" \(3359 characters\)
sed "s/^X//" >'Crack.sh' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
X###
X# For Bourne shell version, CRACK home cannot be relative to ~username
X# (unless you have a really weird 'sh')
X###
X
XCRACK_HOME="/aber/aem/SEC/CRACK32" # This is an ENVIRONMENT var.
Xexport CRACK_HOME
X
Xtrash="/dev/null"
Xremote="FALSE"
Xdefault_bin="generic"
Xtmpfile="/tmp/cpwfs.$$"
Xnet_cf="Scripts/network.conf"
X
X###
X# Check existance of a home directory
X###
X
Xif [ -d $CRACK_HOME ]
Xthen
X cd $CRACK_HOME || exit 1
Xelse
X echo "Error: The directory $CRACK_HOME does not exist."
X echo ""
X echo "Please set the value of CRACK_HOME in the Crack script to the CRACK31"
X echo "installation directory."
X echo ""
X echo "The current working directory is" `pwd`
X exit 1
Xfi
X
X###
X# Announce ourselves.
X###
X
Xecho "Crack 3.2a Password Cracker by ADE Muffett, 1991"
X
X###
X# Check that we have arguments
X###
X
Xif [ "$1" = "" ]
Xthen
X echo "Usage: $0 [options] [bindir] passwdfile [...]"
X echo "Or: $0 -network [options] passwdfile [...]"
X echo "With options:-"
X echo " -v - to produce verbose output (if configured)"
X echo " -nnicevalue - to run niced"
X echo " -rpointfile - to recover a crashed-out job"
X echo " -Rpointfile - to recover (with verify) a crashed-out job"
X exit 1
Xfi
X
X###
X# Parse command line
X###
X
Xargl=""
X
Xwhile :
Xdo
X case $1 in
X -network)
X if [ ! -f $net_cf ]
X then
X echo "$0: error: no file $net_cf"
X exit 1
X fi
X shift
X Scripts/Crack.network $*
X exit 0
X ;;
X
X -remote)
X echo "Invoked: $0 $*"
X set remote="TRUE"
X shift
X ;;
X -v*|-n*|-r*|-R*)
X argl="$argl $1"
X shift
X ;;
X -*)
X echo "Crack: unknown argument $1"
X shift
X ;;
X *)
X break
X ;;
X esac
Xdone
X
X###
X# Test first non-switch argument for existance
X###
X
Xif [ -f "$1" ]
Xthen
X CRACK_ARCH="$CRACK_HOME/$default_bin"
X if [ ! -d $default_bin ]
X then
X echo "Making default binary directory: $default_bin"
X mkdir $default_bin || exit 1
X fi
Xelif [ -d "$1" ]
Xthen
X CRACK_ARCH="$CRACK_HOME/$1"
X shift
Xelse
X echo "Crack: error: There is no directory or file $1."
X echo "Crack: warning: Creating directory $1"
X mkdir $1 || exit 1
X CRACK_ARCH="$CRACK_HOME/$1"
X shift
Xfi
X
Xexport CRACK_ARCH # This is an ENVIRONMENT var.
X
X###
X# Double check the dictionary directory
X###
X
Xif [ ! -d $CRACK_HOME/Dicts ]
Xthen
X echo "Crack: error: There is no directory or file Dicts."
X echo "Crack: warning: Creating directory Dicts"
X mkdir Dicts || exit 1
Xfi
X
X###
X# Now to tidy up a bit
X###
X
Xmake -f Scripts/crack.mf cleanprogs >/dev/null 2>&1
X
Xecho "Using binaries in directory: $CRACK_ARCH"
X
Xcd $CRACK_ARCH || exit 1
X
X###
X# Install makefiles if necessary.
X###
X
Xif [ ! -f Makefile ]
Xthen
X cp $CRACK_HOME/Scripts/install.mf Makefile
Xfi
X
Xmake crack-pwc || exit 1
X
Xcd $CRACK_HOME
X
Xmake -f Scripts/crack.mf dictstamp || exit 1
X
X###
X# Check how we have been invoked : ergo how we get our data.
X###
X
Xif [ "$remote" = "TRUE" ]
Xthen
X cat > $tmpfile
Xelse
X Scripts/joinfiles $* > $tmpfile || exit 1
Xfi
X
Xecho "Backgrounding program. Output will be written to a file in this directory."
X
Xnohup $CRACK_ARCH/crack-pwc $argl -i$tmpfile Dicts/dict.* </dev/null >$trash 2>&1 &
X
Xsleep 1
X
Xtest -f nohup.out && rm nohup.out
X
X###
X# There are horrible timeraces involved in removing $tmpfile, so I dont.
X###
END_OF_FILE
if test 3359 -ne `wc -c <'Crack.sh'`; then
echo shar: \"'Crack.sh'\" unpacked with wrong size!
fi
chmod +x 'Crack.sh'
# end of 'Crack.sh'
fi
if test ! -d 'DictSrc' ; then
echo shar: Creating directory \"'DictSrc'\"
mkdir 'DictSrc'
fi
if test ! -d 'Dicts' ; then
echo shar: Creating directory \"'Dicts'\"
mkdir 'Dicts'
fi
if test ! -d 'Docs' ; then
echo shar: Creating directory \"'Docs'\"
mkdir 'Docs'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(2300 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X-----------------------------------------------------------
X APPENDIX 2 Reasoning for Cracks methods
X BUGS 1 List of known problems
X Crack 2 The "Crack" driver script in csh
X Crack.sh 1 The "Crack" driver script in sh
X DictSrc 1 Directory of source dictionaries
X DictSrc/bad_pws.dat 2 A sample source dictionary
X Dicts 1 Holding store for processed dicts
X Docs 1 Documentation directory
X Docs/README.ms 3 Source code for laconic documentation
X Docs/README.ps 4 Prettified laconic documentation
X MANIFEST 1 This shipping list
X README 1 Laconic documentation
X README.FIRST 1 Introductory Laconic documentation
X Scripts 1 Shellscripts & config files directory
X Scripts/Crack.network 1 The network driver configuration interface
X Scripts/RCrack 1 Frontend to the network program (eg: rsh)
X Scripts/clean 1 Diddy little tidy up script
X Scripts/crack.mf 1 Miscellaneous Makefile called from everywhere
X Scripts/install.mf 1 Another Makefile called from everywhere
X Scripts/joinfiles 1 Formatter for passwd files
X Scripts/makedicts 1 Frontend to dictionary preprocessor
X Scripts/network.conf 1 Empty config file
X Scripts/network.conf.example 1 Example of network configuration file
X Scripts/plaster 1 Diddy little kill script
X Scripts/spotless 1 Diddy little tidy up script
X Sources 1 Cracker source code directory
X Sources/Makefile 1 With a name like that, what do you reckon ?
X Sources/conf.h 1 CONFIGURATION HEADER FILE
X Sources/crack-fcrypt.c 3 fcrypt() [Shock, horror]
X Sources/crack-lib.c 1 Diddy little string manipulation fn()s
X Sources/crack-port.c 1 Portability hooks src
X Sources/crack-pp.c 2 Preprocessor src
X Sources/crack-pwc.c 2 Password cracker src
X Sources/crack.h 1 General header file
X Sources/goodpass.c 2 Example of a sensible password filter
X Sources/speeds.c 1 Test s/w
X Sources/tester.c 1 Test s/w
END_OF_FILE
if test 2300 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(21446 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X
X
X
X
X
X
X
X
X "Crack Version 3.2"
X A Sensible Password Checker for UNIX-
X
X
X Alec D.E. Muffett
X
X Computer Unit, University College of Wales
X Aberystwyth, Wales, SY23 3DB
X a...@aber.ac.uk
X +44 970 622492
X
X
X ABSTRACT
X
X Crack[1] is a freely available program
X designed to find standard UNIX eight-character DES
X encrypted passwords by standard guessing tech-
X niques outlined below. It is written to be flexi-
X ble, configurable and fast, and to be able to make
X use of several networked hosts via the Berkeley
X rsh program (or similar), where possible.
X
X
X
X1. Intent of this program
X
XMy intentions, whilst writing this program, were
X
X1) To provide the average system manager with a simple,
X flexible and fast tool to find passwords which would be
X easily compromised by a dictionary search.
X
X2) To weaken the complacency which has developed amongst
X many (in)?experienced UNIX systems managers about pass-
X word security. Just because the crypt() function cannot
X be reversed does not mean that your passwords are
X secure. If this program helps to raise the overall
X quotient of paranoia just one little bit, then it will
X have served its purpose and is all to the good.
X
XI am quite certain that some childish morons out there will
Xabuse the work that I have put into creating this program.
XIt's up to them how they use it, but if it's used for some
Xillegal purpose it's not my intention, nor my fault. I hope
X_________________________
X [0]
X- UNIX is a trademark of Bell Laboratories.
X [1] Crack is available for anonymous FTP from
Xwuarchive.wustl.edu (128.252.135.4) in ~/packages
X
X
X
X
X August 21, 1991
X
X
X
X
X
X - 2 -
X
X
Xthey get caught.
X
XCrack was not designed to do anything nasty, other than to
Xattack passwords in sensible order. This is why I feel I
Xcan post it to the net without fear of recrimination. This
Xversion of Crack is supplied with a (hopefully) portable
Xversion of fcrypt(), for speed reasons. Fcrypt() is not yet
Xwidely available, but several versions have now been posted
Xto USENET, and with the growing ability to access anonymous
XFTP databases like Archie, I believe that people who really
Xwant access to such programs as fcrypt() will be able to get
Xthem easily. People who need them but don't have the time
Xto look, on the other hand, will not get them. This is not
Xa good thing if you are a systems manager, because it gives
Xthe crackers an advantage. My philosophy is: give it to
Xeveryone, then at least the people who need it can get it.
X
X2. Fcrypt() Statistics
X
XThe version of fcrypt() that comes with Crack is some 3.4
Xtimes faster than the version that was originally supplied
Xto me, and should outperform most others which are publicly
Xavailable. I haven't tried many speed-demon style tricks,
Xbut rather I have gone for portability, elegance and simpli-
Xcity, where applicable 8-). On a DECStation 5000/200,
Xfcrypt() iterates ~550 times per second, and overall, I
Xmeasure this to be 13 times faster than standard crypt().
XThere are faster versions available, but at least I feel
Xfree to redistrubute this version without stepping on any-
Xones toes.
X
XA final note about my motives: If you think that I am a
Xmoron for writing and then distributing this program, and
Xyou think that the program is in itself dangerous, I suggest
Xthat you carefully consider the fact that any moron could
Xhave written this program. Flames to /dev/null, please.
X
X3. Implementation
X
XI have tried to make Crack as portable as possible without
Xcompromising speed. Needless to say, it is imperfect in the
Xthis respect, but I have tried. If you have problems get-
Xting Crack up, please let me know what these problems were,
Xand what system you were trying to put Crack up on. I
Xbelieve that Crack will work on Xenix and various versions
Xof System V, but it may require a little effort if your UNIX
Xis not fairly modern.
X
XThere have been some nasty stories sent back to me about
Xproblems encountered due to the Crack script being written
Xin c-shell. Because of this, I enclose a program Crack.sh
Xwhich is a functionally equivalent script in Bourne shell,
Xusing nohup to kick the cracker off into the background. If
Xyour version of c-shell is non standard (ie: not BSDish) or
X
X
X
X August 21, 1991
X
X
X
X
X
X - 3 -
X
X
Xyou are worried, you may use Crack.sh in Crack's place.
XNote, though, that if you want to use the network options,
Xyou will also have to edit Scripts/RCrack to change the
Xprogram-name that is called on remote machines to Crack.sh.
XFor more on this, see below.
X
XTo use the Crack -network option, you must have rsh, or a
Xsimilar program. rsh is a BSD-ism which has become fairly
Xcommon on non-BSD systems. If you don't have it or some-
Xthing similar, let me know what you do have which might,
Xwith a little ingenuity, do the job, and I shall see what I
Xcan do. Again, have a look in Scripts/RCrack if you want to
Xplay around.
X
X Note: Xenix users and some others have a rcmd pro-
X gram instead of rsh. I'm not sure of the correct
X syntax for this program, but it should not be hard
X to get it to work. There is a note about it in
X Scripts/RCrack
X
X On such System V based systems, users may also be
X missing the BSD function gethostname(). If this
X is so, but you do have the uname() system call,
X define the macro CRACK_UNAME in Sources/conf.h
X instead. This ought to fix the problem, but it may
X need a little user intervention first (it depends
X where your header file for uname() is). Caveat
X Emptor!
X
X4. Method of Password Cracking
X
XCrack does not take the serial approach to password guessing
Xthat other programs like the COPS password cracker does.
XRather, Crack makes two passes over the users' password
Xentries.
X
XThe first pass bases its guesses on the contents of the
Xgecos field (containing the users' real name), and the user-
Xname itself. The first pass is fast and usually very fruit-
Xful, and completes quite quickly. You would be surprised at
Xthe number of spods out there who still think that their
Xmiddle name, backwards and capitalised, is a good password.
X
XThe second pass is made by encrypting several pre-processed
Xdictionaries on the fly, and comparing the results with
Xusers passwords. Crack optimises the number of calls to the
Xencryption function by sorting the user passwords by their
Xencryption salt before loading, so that the dictionaries
Xonly have to be encrypted once for each different salt.
XThis generally saves about 30% of the calls you would have
Xto make to crypt().
X
XThe preprocessed dictionaries are created my merging the
Xsource dictionaries found in the directory DictSrc and then
X
X
X
X August 21, 1991
X
X
X
X
X
X - 4 -
X
X
Xtruncating, sorting and uniq'ing the output from the prepro-
Xcessor. The default dictionaries named are /usr/dict/words
Xwhich provides the bulk of the input data, and
XDictSrc/bad_pws.dat which is meant to provide all of those
Xnon-dictionary passwords, such as 12345678 or qwerty.[2]
X
XIf you wish to add a dictionary of your own, just copy it
Xinto the DictSrc directory and then delete the contents of
Xthe Dicts directory. Your new dictionary will be merged in
Xon the next run. Do not worry about replication of data, as
Xthe preprocessor driver script sorts and uniq's the data
Xbefore putting it into the Dicts directory.
X
XThe formats of the output dictionaries are:
X
Xa) Unique words that have been forced lowercase, forwards.
X These are the most common passwords you will find, thus
X they are tried first.
X
Xb) Dictionary words which have been artificially plural-
X ised, because not many dictionaries contain plurals.
X
Xc) Dictionary words which were supplied in mixed-case (eg:
X Capitalised).
X
Xd) Dictionary words forced lowercase and backwards.
X
Xe) Dictionary words, forced lowercase, with a leading or
X trailing 0 or 1 (this may be extended by hacking
X Sources/crack-pp.c).
X
Xf) Dictionary words, forced uppercase, forwards.
X
Xg) Dictionary words, forced uppercase, backwards.
X
Xh) Dictionary words which were supplied in mixed-case,
X backwards (eg: desilatipaC).
X
X
XThis choice of attack is entirely empirical, my own, and
Xmade up on the spot. It has also been horrendously success-
Xful, and because Crack uses each of these dictionaries in
Xturn, it tends to get passwords faster than a program like
Xthe COPS password cracker which tries words every-which-way
Xfor each user.[3]
X_________________________
X [2] Extra dictionaries (those used in Dan Klein's pa-
Xper, below) can be obtained via anonymous FTP from
Xuunet.uu.net (192.48.96.2) as ~/pub/dictionaries.tar.Z
X [3] For more information, see "Foiling the Cracker: A
XSurvey of, and Improvements to, Password Security" by
XDaniel Klein, available from major FTP sites.
X
X
X
X
X August 21, 1991
X
X
X
X
X
X - 5 -
X
X
X Optimisation Note: Crack has an compile-time
X option, called CRACK_SHORT_PASSWDS, which, if not
X defined, makes the dictionary preprocessor throw
X away words which are less than 5 characters long.
X The reasoning for this is that many sites, with a
X semi-sensible passwd program, will not have pass-
X words shorter than 5 characters long.
X
X It is up to you whether you bother testing these
X short passwords, but I would recommend that you do
X so at least once, to be safe. (Setting the option
X also leads to having smaller pre-processed dic-
X tionaries. The option, however, is defined by
X default)
X
X5. Installation
X
XCrack is one of those most unusual of beasties, a self-
Xinstalling program. Once the necessary configuration
Xoptions have been set, the executables are created via
X'make' by running the main shellscript.
X
XSome people have complained about this apparent weirdness,
Xbut it has grown up with Crack ever since the earliest net-
Xwork version, when I could not be bothered to log into
Xseveral different machines with several different architec-
Xtures, just in order to build the binaries.
X
XCrack needs to know where it has been installed. Please
Xedit the CRACK_HOME variable in the Crack shellscript to the
Xcorrect value. This variable should be set to an absolute
Xpath name (relative to ~user is OK) through which the direc-
Xtory containing Crack may be accessed on all the machines
Xthat Crack will be run on.
X
XThe other bit of installation you will have to do is decide
Xwhether you will want to use the -network option. If you do,
Xedit the file Sources/conf.h and define the CRACK_NETWORK
Xsymbol. This forces Crack to create all of its output files
Xwith an embedded hostname (obtained by the gethostname()
Xroutine) so that you can keep track of output from all over
Xthe network. If you have no gethostname() but have a
Xuname() system call, you can use that instead, by defining
XCRACK_UNAME in Sources/conf.h.
X
XYou will then have to generate a Scripts/network.conf file.
XThis contains a list of hostnames to rsh to, what their
Xbinary type is (useful when running a network Crack on
Xseveral different architectures), a guesstimate of their
Xrelative power (take your slowest machine as unary, and
Xmeasure all others relative to it), and a list of per-host
Xdefault flags. There is an example of such a file provided
Xin the Scripts directory - take a look at it.
X
X
X
X
X August 21, 1991
X
X
X
X
X
X - 6 -
X
X
XI also recommend that you play around with the #defines in
Xthe file Sources/conf.h. Each switch has a small note
Xexplaining its meaning. Where I've been in doubt about the
Xportability of certain library functions, usually I've re-
Xwritten it, so it shouldn't be much of a problem. Let me
Xknow of your problems. 8-).
X
X6. Crack Usage
X
X
XCrack [options] [bindir] /etc/passwd [...other passwd files]
X
XCrack -network [options] /etc/passwd [...other passwd files]
X
X
XWhere bindir is the optional name of the directory where you
Xwant the binaries installed. This is useful where you want
Xto be able to run versions of Crack on several different
Xarchitectures. If bindir does not exist, a warning will be
Xissued, and the directory, created.
X
X Note: bindir defaults to the name generic if not
X supplied.
X
X Yellow Pages (NIS) Users: I have had some queries
X about how to get Crack running from a YP password
X file. There are several methods, but by far the
X simplest is to generate a passwd format file by
X running:-
X
X ypcat passwd > passwd.yp
X
X and then running Crack on this file.
X
X7. Options
X
X-network
X Throws Crack into network mode, in which it reads the
X Scripts/network.conf file, splits its input into chunks
X which are sized according to the power of the target
X machine, and calls rsh to run Crack on that machine.
X Options for Crack running on the target machine may be
X supplied on the command line (eg: verbose or recover
X mode), or in the network.conf file if they pertain to
X specific hosts (eg: nice() values).
X
X-v Sets verbose mode, whereby Crack will print every guess
X it is trying on a per-user basis. This is a very quick
X way of flooding your filestore. If you undefine the
X CRACK_VERBOSE symbol in Sources/conf.h, verbose mode
X will be permanently disabled.
X
X-nvalue
X Sets the process to be nice()ed to value, so that the
X
X
X
X August 21, 1991
X
X
X
X
X
X - 7 -
X
X
X switch -n19 sets the Crack process to run at the lowest
X priority.
X
X-rpointfile
X This is only for use when running in recover mode.
X When a running Crack starts pass 2, it periodically
X saves its state in a file named point.<pid> or
X point.<hostname>.<pid> depending on your naming conven-
X tion (see "Installation", above). This file can be
X used to recover where you were should a host crash.
X Simply invoke Crack in exactly the same manner as the
X last time, with the addition of the -rpoint.file.name
X switch. Crack will startup and read the file, and jump
X to slightly before where it left off. If you are
X cracking a very large password file, this can save
X oodles of time after a crash.
X
X If you are running a network Crack, then the jobs
X will again be spawned onto all the machines of the
X original Crack. The program will then check that
X the host it is running on is the same as is men-
X tioned in the pointfile. If it is not, it will
X silently die. Thus, assuming that you supply the
X same input data and do not change your
X network.conf file, Crack should pick up exactly
X where it left off. This is a bit inelegant, but
X it's better than nothing at the moment.
X
X8. Multiprocessing and parallelism
X
XThe method of error recovery outlined above causes headaches
Xfor users who want to do multiprocessing on parallel archi-
Xtectures. Crack is in no way parallel, and because of the
Xway it's structured, readind stdin from shellscript fron-
Xtends, it is a pain to divide the work amongst several
Xprocesses via fork()ing.
X
XThe hack solution to get several copies of Crack running on
Xone machine with n processors at the moment is to run with
Xthe CRACK_NETWORK option enabled, and insert n copies of the
Xentry for your parallel machine into the
XScripts/network.conf file. If you use the -r option in these
Xcircumstances however, you will get n copies of the
Xrecovered process running, only one of them will have the
Xcorrect input data. I'm working on this. My current solu-
Xtion is to save the current username in the checkpoint file,
Xand test it on startup, but doing this may break your
Xrecovery if you supply different input data (so that the
Xdata is sorted even slightly differently). Hohum. If you
Xwant to use this verify username facility, use -R in place
Xof -r.
X
XAs for not using the network.conf file to provide multipro-
Xcessing, I'm working on it.
X
X
X
X August 21, 1991
X
X
X
X
X
X - 8 -
X
X
X9. Notes on fast crypt() implementations
X
XThe stdlib version of the crypt() subroutine is incredibly
Xslow. It is a massive bottleneck to the execution of Crack
Xand on typical platforms that you get at universities, it is
Xrare to find a machine which will achieve more than 50 stan-
Xdard crypt()s per second. On low-end diskless workstations,
Xyou may expect 2 or 3 per second. It was this slowness of
Xthe crypt() algorithm which originally supplied much of the
Xsecurity UNIX needed.[4]
X
XHowever, there are now many implementations of faster ver-
Xsions of crypt() to be found on the network. The one sup-
Xplied with Crack v3.2 and upwards is called fcrypt().
X
Xfcrypt() was originally written in May 1986 by Robert
XBaldwin at MIT, and is a good version of the crypt() subrou-
Xtine. I received a copy from Icarus Sparry at Bath Univer-
Xsity, who had made a couple of portability enhancements to
Xthe code.
X
XI rewrote most of the tables and the KeySchedule generating
Xalgorithm in the original fdes-init.c to knock 40% off the
Xexecution overhead of fcrypt() in the form that it was
Xshipped to me. I inlined a bunch of stuff, put it into a
Xsingle file, got some advice from Matt Bishop and Bob
XBaldwin [both of whom I am greatly indebted to] about what
Xto do to the xform() routine and to the fcrypt function
Xitself, and tidied up some algorithms. I've also added more
Xlookup tables and reduced several formula for faster use.
Xfcrypt() is now barely recognisable as being based on its
Xformer incarnation.
X
XOn a DecStation 5000/200, it is also ~13 times faster than
Xthe standard crypt (your mileage may vary with other archi-
Xtectures and compilers). This speed puts fcrypt() into the
X"moderately fast" league of crypt implementations. By using
Xfcrypt() with Crack, I extracted 135 passwords from my stan-
Xdard 1087 user password file in a little over 1 hour using 3
Xnetworked machines. This is from a moderately good password
Xfile.
X
XWhy am I saying this sort of thing ? Am I scaremongering ?
XIn a word, yes.
X
XIf a fast version of crypt() is wired into a program like
XCrack it can break a poorly passworded site open in minutes.
XThere are such programs available, eg: the "Killer Cracker"
Xwritten by the anonymous "Doctor Dissector", with anonymous
Xmotives. It comes with a modified version of Baldwin's
X_________________________
X [4] See: "Password Security, A Case History" by Bob
XMorris & Ken Thomson, in the UNIX Programmer Docs.
X
X
X
X August 21, 1991
X
X
X
X
X
X - 9 -
X
X
Xfcrypt, as a MS-DOS executable with a GNU copyleft licence.
X
XThe point that needs to be hammered home is that unless
Xsomething is done, and done soon, about the general quality
Xof passwords on UNIX systems, then in the near future our
Xdoors will be wide open to people who have programs like
XCrack and questionable motives.
X
X10. Solutions and Conclusions
X
XWhat can be done about this form of attack ?
X
XYou must get a drop-in replacement for the passwd and
Xyppasswd commands; one which will stop people from choosing
Xbad passwords in the first place. There are several pro-
Xgrams to do this; Matt Bishop's passwd+ and Clyde Hoover's
Xnpasswd program are good examples which are freely avail-
Xable. Consult an Archie database for more details on where
Xyou can get them from.
X
XA little common-sense is all that is required to vet pass-
Xwords: I enclose a module in the Sources directory
Xgoodpass.c which I use in a modified version of the yppasswd
Xin order to provide some security. It is quite heavily cus-
Xtomised for use in the UK, but it should be easily portable.
XThe routine is invoked:
X
X
X char *retval = GoodPass(char *input);
X
X
Xwhere input is the password under test, and retval will be
Xset either to NULL (if the password is OK) or to a diagnos-
Xtic string which says what is wrong with the password. It
Xis far less complex than a system such as passwd+, but still
Xeffective enough to make a password file withstand Crack.
XIt would be nice if an organisation (such as CERT?) could be
Xpersuaded to supply skeletons of sensible passwd commands
Xfor the public good, as well as an archive of security
Xrelated utilities[5] on top of the excellent COPS. However,
Xfor UNIX security to improve on a global scale, we will also
Xrequire pressure on the vendors, so that programs are writ-
Xten correctly from the beginning.
X
X
X
X
X
X
X_________________________
X [5] COPS is available for anonymous FTP from
Xcert.sei.cmu.edu (128.237.253.5) in ~/cops
X
X
X
X
X August 21, 1991
X
X
END_OF_FILE
if test 21446 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'README.FIRST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README.FIRST'\"
else
echo shar: Extracting \"'README.FIRST'\" \(1310 characters\)
sed "s/^X//" >'README.FIRST' <<'END_OF_FILE'
XThis is Crack, v3.2a+fcrypt() : A sensible password cracker for Unix.
X
XDocumentation provided is in the "README" file, which I've handhacked
Xdown to a unutterably boring text file. The "README.ms" file in "Docs"
Xgenerates a far prettier output using "nroff -ms", and "Docs/README.ps"
Xis even prettier still. I suggest that you start br reading one of
Xthese files.
X
XCrack+fcrypt() works on Ultrix and SunOS, and probably on a lot of other
Xthings too. AIX has problems with creating a crypt compatible fcrypt().
XFor a list of the current problems, see the BUGS file. At worst, just
Xrun with the version of 'crypt()' which comes with your system.
X
XTo install: Just create a directory to keep it all in, move the shar
Xfiles into the directory, and run them.
X
XThe most patently obvious difference from the last release is that I
Xhave provided two versions of the driver script "Crack" - one in 'csh'
Xand one in 'sh'. If the 'sh' one works out okay, I'll eventually trash
Xthe 'csh' version.
X
XIf you have problems, let me know, so long as they're not too personal.
X
X- Alec 8-)
X
X--
XINET: a...@aber.ac.uk JANET: a...@uk.ac.aber BITNET: aem%aber@ukacrl
XUUCP: ...!mcsun!ukc!aber!aem ARPA: aem%uk.ac...@nsfnet-relay.ac.uk
XSNAIL: Alec Muffett, Computer Unit, Llandinam UCW, Aberystwyth, UK, SY23 3DB
END_OF_FILE
if test 1310 -ne `wc -c <'README.FIRST'`; then
echo shar: \"'README.FIRST'\" unpacked with wrong size!
fi
# end of 'README.FIRST'
fi
if test ! -d 'Scripts' ; then
echo shar: Creating directory \"'Scripts'\"
mkdir 'Scripts'
fi
if test -f 'Scripts/Crack.network' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/Crack.network'\"
else
echo shar: Extracting \"'Scripts/Crack.network'\" \(2052 characters\)
sed "s/^X//" >'Scripts/Crack.network' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
X###
X# This program reads the network.conf and breaks up the sorted password
X# file and kicks "Crack" up on all the machines and feeds the file to it.
X###
X
X###
X# Okay, if you don't like this bit of code, YOU think of a totally
X# portable way to do this - in shell scripts without using PERL - Alec.
X###
X
Xcf=Scripts/network.conf
Xtf=/tmp/mcpwfs.$$
X
X###
X# Check that the config file is in place
X###
X
Xif [ ! -f $cf -o ! -s $cf ]
Xthen
X echo "Crack.network: empty or missing config file: $cf"
X exit 1
Xfi
X
Xargs=""
Xfiles=""
X
Xfor i in $*
Xdo
X if [ -f "$i" ]
X then
X files="$files $i"
X else
X args="$args $i"
X fi
Xdone
X
Xecho "Merging data."
X
XScripts/joinfiles $files > $tf
Xlines=`wc -l < $tf`
X
Xecho "Starting analysis for Network-Crack."
X
Xcat $cf |
Xgrep -v '^#' |
Xsort +2 -n |
Xawk '
XBEGIN {
X hostcount = 0;
X totalweight = 0;
X linecount = '"$lines"';
X iargs = "'"$args"'";
X file = "'"$tf"'";
X}
X
X/^[a-zA-Z0-9]/ {
X hostname[hostcount] = $1;
X cputype[hostcount] = $2;
X weight[hostcount] = $3;
X totalweight += $3;
X args[hostcount] = iargs;
X for (i = 4; i <= NF && substr($i,1,1) != "#"; i++)
X {
X args[hostcount] = args[hostcount] " " $i;
X }
X hostcount++;
X}
X
XEND {
X done = 1;
X todo = linecount;
X print "echo Users:", linecount;
X print "echo Remote Hosts:", hostcount;
X
X for (i = 0; i < hostcount; i++)
X {
X if (i < hostcount - 1)
X {
X slice = weight[i] / totalweight; # fraction
X slice *= linecount; # percentage
X slice = int(slice); # round down
X todo -= slice; # remainder
X } else
X {
X slice = todo; # fastest machine gets the rest.
X todo = 0;
X }
X if (slice > 0)
X {
X print "echo Calling", hostname[i], "for", slice, "users";
X line = sprintf("Scripts/RCrack %s %s %d %d %s < %s\n", \
X hostname[i],\
X cputype[i], \
X done, \
X done + slice - 1, \
X args[i], \
X file);
X print "echo", line;
X print line;
X }
X done += slice;
X }
X}' | sh # I'll bet you didn't expect this...
X
Xrm $tf
END_OF_FILE
if test 2052 -ne `wc -c <'Scripts/Crack.network'`; then
echo shar: \"'Scripts/Crack.network'\" unpacked with wrong size!
fi
chmod +x 'Scripts/Crack.network'
# end of 'Scripts/Crack.network'
fi
if test -f 'Scripts/RCrack' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/RCrack'\"
else
echo shar: Extracting \"'Scripts/RCrack'\" \(590 characters\)
sed "s/^X//" >'Scripts/RCrack' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
Xremote_shell="rsh" # This could be 'rcmd' for, say, Xenix stuff
Xcrack_prog="Crack" # This could be "Crack.sh", for users with csh probs.
X
Xhost=$1
Xshift
Xtype=$1
Xshift
Xstartline=$1
Xshift
Xstopline=$1
Xshift
Xargs="$*"
X
Xawk 'NR >= '"$startline"' && NR <= '"$stopline"'{print $0;} {next;}' |
X$remote_shell $host "$CRACK_HOME/$crack_prog" -remote $args $type
X #^^^^^^^^^^^^^^^^^^^^^^
X # This is quoted to allow ~username through unexpanded
END_OF_FILE
if test 590 -ne `wc -c <'Scripts/RCrack'`; then
echo shar: \"'Scripts/RCrack'\" unpacked with wrong size!
fi
chmod +x 'Scripts/RCrack'
# end of 'Scripts/RCrack'
fi
if test -f 'Scripts/clean' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/clean'\"
else
echo shar: Extracting \"'Scripts/clean'\" \(189 characters\)
sed "s/^X//" >'Scripts/clean' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
Xmake -f Scripts/crack.mf clean > /dev/null 2>&1
END_OF_FILE
if test 189 -ne `wc -c <'Scripts/clean'`; then
echo shar: \"'Scripts/clean'\" unpacked with wrong size!
fi
chmod +x 'Scripts/clean'
# end of 'Scripts/clean'
fi
if test -f 'Scripts/crack.mf' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/crack.mf'\"
else
echo shar: Extracting \"'Scripts/crack.mf'\" \(776 characters\)
sed "s/^X//" >'Scripts/crack.mf' <<'END_OF_FILE'
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
X###
X# Add other dictionaries here, absolute path, or relative to $CRACK_HOME
X#
XDICTSRC= /usr/dict/words DictSrc/*
X
X###
X# Not-so configurable bitz...
X###
XPPDRIVER= Scripts/makedicts
XSRCDIR= Sources
XDICTDIR= Dicts
XDS= $(DICTDIR)/dictstamp
X
Xdictstamp: $(DS)
X
X###
X# You could have a dependency here, but it would make an awfful mess of
X# using wildcards
X$(DS):
X @echo Using Sources '$(DICTSRC)'
X ( cd $$CRACK_ARCH && make crack-pp )
X $(PPDRIVER) $(DICTDIR) $(DICTSRC)
X touch $(DS)
X
Xcleanprogs:
X -( cd $(SRCDIR) && make clean )
X
Xclean: cleanprogs
X -rm -f die.* out.* point.* dict.? nohup.out
X
Xspotless: clean
X -( cd $(DICTDIR) && rm dict* )
END_OF_FILE
if test 776 -ne `wc -c <'Scripts/crack.mf'`; then
echo shar: \"'Scripts/crack.mf'\" unpacked with wrong size!
fi
# end of 'Scripts/crack.mf'
fi
if test -f 'Scripts/install.mf' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/install.mf'\"
else
echo shar: Extracting \"'Scripts/install.mf'\" \(375 characters\)
sed "s/^X//" >'Scripts/install.mf' <<'END_OF_FILE'
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
XSD= ../Sources
X
Xsource: crack-pp crack-pwc
X touch source
X
Xcrack-pp: $(SD)/crack-pp.c $(SD)/conf.h
X ( cd $(SD) ; make crack-pp )
X cp $(SD)/crack-pp .
X
Xcrack-pwc: $(SD)/crack-pwc.c $(SD)/conf.h
X ( cd $(SD) ; make crack-pwc )
X cp $(SD)/crack-pwc .
END_OF_FILE
if test 375 -ne `wc -c <'Scripts/install.mf'`; then
echo shar: \"'Scripts/install.mf'\" unpacked with wrong size!
fi
# end of 'Scripts/install.mf'
fi
if test -f 'Scripts/joinfiles' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/joinfiles'\"
else
echo shar: Extracting \"'Scripts/joinfiles'\" \(844 characters\)
sed "s/^X//" >'Scripts/joinfiles' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
Xwarn=out.initial.$$
X
X###
X# Empty the output file...
X> $warn
X
X###
X# As Walt Disney would say, we start with a simple bracket:-
X
X(
Xfor file in $*
Xdo
X
Xawk '
XBEGIN {
X FS = ":";
X warn="'$warn'";
X file = "'$file'";
X date = "'"`date`"'";
X date = substr(date, 5, 15);
X}
X
Xsubstr($2,1,1) == "!" || substr($2,1,1) == "*" {
X printf("join: %s User %s (in %s) has a locked password.\n", \
X date, $1, file) >> warn;
X next;
X}
X
X$2 == "" {
X printf("join: %s Warning! %s (%s in %s) has a NULL password!\n", \
X date, $1, $7, file) >> warn;
X next;
X}
X
X/^[A-Za-z]/ {
X print file ":" $0;
X}
X ' < $file
Xdone
X
X###
X# Using a pipe is a bit faster - no bloody fs action.
X###
X
X) | sort -t: +2 # sort all of them by salt
X
Xexit 0
END_OF_FILE
if test 844 -ne `wc -c <'Scripts/joinfiles'`; then
echo shar: \"'Scripts/joinfiles'\" unpacked with wrong size!
fi
chmod +x 'Scripts/joinfiles'
# end of 'Scripts/joinfiles'
fi
if test -f 'Scripts/makedicts' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/makedicts'\"
else
echo shar: Extracting \"'Scripts/makedicts'\" \(449 characters\)
sed "s/^X//" >'Scripts/makedicts' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
Xpp="$CRACK_ARCH/crack-pp"
Xdictdir=$1
X
Xshift
X
Xif [ ! -f $pp ]
Xthen
X echo "$0: No preprocessor $pp! How the hell did this happen!"
X exit 1
Xfi
X
Xrm -f $dictdir/dict.*
X
X$pp $*
X
Xecho "Compacting. This may take some time..."
X
Xfor i in dict.*
Xdo
X sort -r $i | uniq > $dictdir/$i
X rm -f $i
X echo Done $i
Xdone
X
Xexit 0
END_OF_FILE
if test 449 -ne `wc -c <'Scripts/makedicts'`; then
echo shar: \"'Scripts/makedicts'\" unpacked with wrong size!
fi
chmod +x 'Scripts/makedicts'
# end of 'Scripts/makedicts'
fi
if test -f 'Scripts/network.conf' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/network.conf'\"
else
echo shar: Extracting \"'Scripts/network.conf'\" \(188 characters\)
sed "s/^X//" >'Scripts/network.conf' <<'END_OF_FILE'
X###
X# Format of this file :-
X###
X# hostname binary_directory relative_power args # comments
X###
Xaberda mipsel 10 -n19
Xaberdb mipsel 10 -n19
Xaberdc mipsel 11
Xaberdq sun4 8
END_OF_FILE
if test 188 -ne `wc -c <'Scripts/network.conf'`; then
echo shar: \"'Scripts/network.conf'\" unpacked with wrong size!
fi
# end of 'Scripts/network.conf'
fi
if test -f 'Scripts/network.conf.example' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/network.conf.example'\"
else
echo shar: Extracting \"'Scripts/network.conf.example'\" \(381 characters\)
sed "s/^X//" >'Scripts/network.conf.example' <<'END_OF_FILE'
X###
X# Format of this file :-
X###
X# hostname binary_directory relative_power args # comments
X###
Xaberdc mipsel 11 # DS5000/200
Xaberda mipsel 10 -n10 # DEC 5830
Xaberdb mipsel 10 -n10 # DEC 5830
Xaberdq sun4 8 # Sun 4/330
Xdecgca mipsel 5 -n19 # DS3100
Xsunga sun3 1 -n19 # Sun 3/50
Xsungb sun3 1 -n19 # Sun 3/50
Xsungc sun3 1 -n19 # Sun 3/50
END_OF_FILE
if test 381 -ne `wc -c <'Scripts/network.conf.example'`; then
echo shar: \"'Scripts/network.conf.example'\" unpacked with wrong size!
fi
# end of 'Scripts/network.conf.example'
fi
if test -f 'Scripts/plaster' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/plaster'\"
else
echo shar: Extracting \"'Scripts/plaster'\" \(377 characters\)
sed "s/^X//" >'Scripts/plaster' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
X###
X# This program provides a quick network murder if running "Crack -network"
X###
X# The name is Chris Samuel's fault... "Plaster the Cracks" indeed...
X# Mail admiration of this joke to cc...@aber.ac.uk
X###
X
Xfor i in ./die.*
Xdo
X $i
Xdone
END_OF_FILE
if test 377 -ne `wc -c <'Scripts/plaster'`; then
echo shar: \"'Scripts/plaster'\" unpacked with wrong size!
fi
chmod +x 'Scripts/plaster'
# end of 'Scripts/plaster'
fi
if test -f 'Scripts/spotless' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Scripts/spotless'\"
else
echo shar: Extracting \"'Scripts/spotless'\" \(192 characters\)
sed "s/^X//" >'Scripts/spotless' <<'END_OF_FILE'
X#!/bin/sh
X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
Xmake -f Scripts/crack.mf spotless > /dev/null 2>&1
END_OF_FILE
if test 192 -ne `wc -c <'Scripts/spotless'`; then
echo shar: \"'Scripts/spotless'\" unpacked with wrong size!
fi
chmod +x 'Scripts/spotless'
# end of 'Scripts/spotless'
fi
if test ! -d 'Sources' ; then
echo shar: Creating directory \"'Sources'\"
mkdir 'Sources'
fi
if test -f 'Sources/Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/Makefile'\"
else
echo shar: Extracting \"'Sources/Makefile'\" \(1572 characters\)
sed "s/^X//" >'Sources/Makefile' <<'END_OF_FILE'
X###
X# Makefile for the CRACK suite V3.2, (c) ADE Muffett, Aug 1991
X###
X
X###
X# Configurtable bitz...
X###
X
XCC= cc
XCFLAGS= -O2
XLIBS=
XSHELL= /bin/sh
X
X###
X# Not so configurable bitz...
X###
X
XPWC= crack-pwc
XPP= crack-pp
X
X###
X# There is some redundancy in using CRACKMOD like this, as opposed to a
X# library, but it's more portable than trying to use 'ar' - as Chris Lewis
X# pointed out... SWTF.
X###
X
XCRACKMOD= crack-lib.o crack-fcrypt.o crack-port.o
X
X###
X# Default target
X###
X
Xall: $(PP) $(PWC)
X
X$(PP): $(CRACKMOD) crack-pp.o
X $(CC) $(CFLAGS) -o $@ crack-pp.o $(CRACKMOD) $(LIBS)
X
X$(PWC): $(CRACKMOD) crack-pwc.o
X $(CC) $(CFLAGS) -o $@ crack-pwc.o $(CRACKMOD) $(LIBS)
X
Xcrack-pp.c: crack.h
X
Xcrack-pwc.c: crack.h
X
Xcrack-lib.c: crack.h
X
Xcrack.h: conf.h
X touch crack.h
Xconf.h:
X
Xclean:
X -rm -f $(PP) $(PWC) *.o *.u *.a
X -rm -f tester *.pixie *.Addrs *.Counts
X -rm -f speedcrypt speedfcrypt speedxform
X
X###
X# These targets below are for fcrypt() development only
X###
X
XPIXIEF = -procedures -heavy -invocations -zero
X
Xtests: speedcrypt tester speedxform speedfcrypt
X -./speedcrypt
X -./speedfcrypt
X -./speedxform
X -./tester
X
Xspeedfcrypt: speeds.c $(CRACKMOD)
X $(CC) -DT1 -o speedfcrypt speeds.c $(CRACKMOD)
X
Xspeedxform: speeds.c $(CRACKMOD)
X $(CC) -DT2 -o speedxform speeds.c $(CRACKMOD)
X
Xspeedcrypt: speeds.c $(CRACKMOD)
X $(CC) -o speedcrypt speeds.c $(CRACKMOD)
X
Xtester: tester.o $(CRACKMOD)
X $(CC) -o tester tester.o $(CRACKMOD)
X
Xtester.pixie: tester
X pixie -o tester.pixie tester
X
Xprof: tester.pixie
X time tester.pixie
X prof -pixie tester $(PIXIEF)
END_OF_FILE
if test 1572 -ne `wc -c <'Sources/Makefile'`; then
echo shar: \"'Sources/Makefile'\" unpacked with wrong size!
fi
# end of 'Sources/Makefile'
fi
if test -f 'Sources/conf.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/conf.h'\"
else
echo shar: Extracting \"'Sources/conf.h'\" \(3459 characters\)
sed "s/^X//" >'Sources/conf.h' <<'END_OF_FILE'
X#include <stdio.h>
X#include <ctype.h>
X#include <pwd.h>
X#include <signal.h>
X
X#ifdef BSD
X#define strchr(a,b) index(a,b)
X#endif /* BSD */
X
X/*
X * Switch for my use - if defined, overrides the defaults below and sets up
X * my own. It's simplest if you undefine and ignore this switch.
X */
X
X#define DEVELOPMENT_VERSION
X
X/* !!!! EVERYBODY ELSE START HERE !!!! */
X
X/*
X * if defined, this will insert code for verbose options
X */
X
X#define CRACK_VERBOSE
X
X/*
X * define this if you have _toupper() - check your manpages
X */
X
X#undef FAST_TOCASE
X
X/*
X * define this if you are on a Sys V type system with a uname() system call
X * and have no gethostname() - it fakes up a BSD gethostname() so you can use
X * CRACK_NETWORK; see crack-port.c
X */
X
X#undef CRACK_UNAME
X
X/*
X * define this if you are running multiple Cracks over a network; if you
X * aren't using "rsh" to do this, edit "Scripts/RCrack" as well
X */
X
X#undef CRACK_NETWORK
X
X/*
X * define this to search gecos entry for possible passwords - I RECOMMEND
X * THIS VERY VERY STRONGLY
X */
X
X#define CRACK_GECOS
X
X/*
X * define this to make a dictionary pass of pluralised words
X */
X
X#define CRACK_PLURAL
X
X/*
X * define this to make a dictionary pass of words with leading and trailing
X * 0's and 1's. If you want to add other leading/trailing characters, edit
X * the "trailing_chars[]" string in "crack-pp.c"
X */
X
X#define CRACK_TRAILING
X
X/*
X * define this to print the password if you crack it
X */
X
X#define CRACK_PRINTOUT
X
X/*
X * if defined, tries guesses < 5 chars long - this wastes time if you are
X * unlikely to have REALLY short passwords, try it once though.
X */
X
X#define CRACK_SHORT_PASSWDS
X
X/*
X * if defined, do sanity checks on the DES password - this gets round expiry
X * mechanisms appending extra characters to signify "things"
X */
X
X#define CRACK_PW_VERIFY
X
X/*
X * define this if you are using fcrypt() - you might not want to if
X * fcrypt() doesn't work properly
X */
X
X#define FCRYPT
X
X/*
X * The following symbols pertain ONLY to fcrypt() usage
X */
X
X/*
X * if defined use builtin clearing in preference to using bzero(), for 4 or 8
X * byte long ints
X */
X
X#define BUILTIN_CLEAR
X
X/*
X * define if you have a bzero and do not want to use BUILTIN_CLEAR
X */
X
X#define BZERO
X
X/*
X * define this if you have a 4 byte "long_int" on RISC machines and want a
X * speedup - it should not hurt CISC machines either
X */
X
X#undef FDES_4BYTE
X
X/*
X * undef this if your compiler knows the fact that 6*x == x<<1 + x<<2
X */
X
X#undef BRAINDEAD6
X
X/*
X * Personal stuff only - I recommend you ignore stuff below this line, unless
X * you know what you're doing
X */
X
X#ifdef DEVELOPMENT_VERSION
X/*
X * for my personal use, this is my configuration on a DS5000/200
X */
X#undef BRAINDEAD6
X
X#ifndef BUILTIN_CLEAR
X#define BUILTIN_CLEAR
X#endif /* BUILTIN_CLEAR */
X
X#undef BZERO
X
X#ifndef CRACK_GECOS
X#define CRACK_GECOS
X#endif /* CRACK_GECOS */
X
X#ifndef CRACK_NETWORK
X#define CRACK_NETWORK
X#endif /* CRACK_NETWORK */
X
X#ifndef CRACK_PLURAL
X#define CRACK_PLURAL
X#endif /* CRACK_PLURAL */
X
X#ifndef CRACK_PRINTOUT
X#define CRACK_PRINTOUT
X#endif /* CRACK_PRINTOUT */
X
X#ifndef CRACK_PW_VERIFY
X#define CRACK_PW_VERIFY
X#endif /* CRACK_PW_VERIFY */
X
X#undef CRACK_SHORT_PASSWDS
X
X#ifndef CRACK_TRAILING
X#define CRACK_TRAILING
X#endif /* CRACK_TRAILING */
X
X#undef CRACK_UNAME
X
X#undef CRACK_VERBOSE
X
X#undef FAST_TOCASE
X
X#ifndef FCRYPT
X#define FCRYPT
X#endif /* FCRYPT */
X
X#ifndef FDES_4BYTE
X#define FDES_4BYTE
X#endif /* FDES_4BYTE */
X
X#endif /* DEVELOPMENT VERSION */
END_OF_FILE
if test 3459 -ne `wc -c <'Sources/conf.h'`; then
echo shar: \"'Sources/conf.h'\" unpacked with wrong size!
fi
# end of 'Sources/conf.h'
fi
if test -f 'Sources/crack-lib.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack-lib.c'\"
else
echo shar: Extracting \"'Sources/crack-lib.c'\" \(1756 characters\)
sed "s/^X//" >'Sources/crack-lib.c' <<'END_OF_FILE'
X#include "crack.h"
X
X/*
X * This program is copyright (c) Alec Muffett 1991 except for certain
X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
X * Sparry and Alec Muffett. The author(s) disclaims all responsibility or
X * liability with respect to it's usage or its effect upon hardware or
X * computer systems. This software is in the public domain and is freely
X * redistributable PROVIDED that this notice remains intact.
X */
X
Xvoid
XTrim (string) /* remove trailing whitespace from a string */
X register char *string;
X{
X register char *ptr;
X
X for (ptr = string; *ptr; ptr++);
X while ((--ptr >= string) && isspace (*ptr));
X *(++ptr) = '\0';
X}
X
Xchar *
XReverse (str) /* return a pointer to a reversal */
X register char *str;
X{
X register int i;
X register int j;
X register char *ptr;
X static char area[STRINGSIZE];
X
X j = i = strlen (str);
X while (*str)
X {
X area[--i] = *str++;
X }
X area[j] = '\0';
X return (area);
X}
X
Xchar *
XUppercase (str) /* return a pointer to an uppercase */
X register char *str;
X{
X register char *ptr;
X static char area[STRINGSIZE];
X
X ptr = area;
X while (*str)
X {
X *(ptr++) = islower (*str) ? toupper (*str) : *str;
X str++;
X }
X *ptr = '\0';
X
X return (area);
X}
X
Xchar *
XLowercase (str) /* return a pointer to an lowercase */
X register char *str;
X{
X register char *ptr;
X static char area[STRINGSIZE];
X
X ptr = area;
X while (*str)
X {
X *(ptr++) = isupper (*str) ? tolower (*str) : *str;
X str++;
X }
X *ptr = '\0';
X
X return (area);
X}
X
Xchar *
XClone (string)
X char *string;
X{
X int len;
X char *retval;
X
X retval = (char *) malloc (strlen (string) + 1);
X strcpy (retval, string);
X return (retval);
X}
END_OF_FILE
if test 1756 -ne `wc -c <'Sources/crack-lib.c'`; then
echo shar: \"'Sources/crack-lib.c'\" unpacked with wrong size!
fi
# end of 'Sources/crack-lib.c'
fi
if test -f 'Sources/crack-port.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack-port.c'\"
else
echo shar: Extracting \"'Sources/crack-port.c'\" \(296 characters\)
sed "s/^X//" >'Sources/crack-port.c' <<'END_OF_FILE'
X#include "crack.h"
X
X#ifdef CRACK_UNAME
X
X#include <sys/utsname.h>
X
Xint
Xgethostname (name, namelen)
X char *name;
X int namelen;
X{
X struct utsname uts;
X if (uname (&uts))
X {
X return (-1);
X }
X strncpy (name, uts.nodename, namelen - 1);
X return (0);
X}
X
X#endif /* CRACK_UNAME */
END_OF_FILE
if test 296 -ne `wc -c <'Sources/crack-port.c'`; then
echo shar: \"'Sources/crack-port.c'\" unpacked with wrong size!
fi
# end of 'Sources/crack-port.c'
fi
if test -f 'Sources/crack.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack.h'\"
else
echo shar: Extracting \"'Sources/crack.h'\" \(707 characters\)
sed "s/^X//" >'Sources/crack.h' <<'END_OF_FILE'
X/*
X * This program is copyright (c) Alec Muffett 1991 except for certain
X * portions of code ("fdes-crypt.c") copyright (c) Robert Baldwin, Icarus
X * Sparry and Alec Muffett. The author(s) disclaims all responsibility or
X * liability with respect to it's usage or its effect upon hardware or
X * computer systems. This software is in the public domain and is freely
X * redistributable PROVIDED that this notice remains intact.
X */
X
X#include "conf.h"
X
X#define STRINGSIZE 255
X
Xvoid Trim ();
Xchar *Reverse ();
Xchar *Uppercase ();
Xchar *Lowercase ();
Xchar *Clone ();
X
X#ifdef FAST_TOCASE
X#define toupper(x) _toupper(x)
X#define tolower(x) _tolower(x)
X#endif
X
X#ifdef FCRYPT
X#define crypt(a,b) fcrypt(a,b)
X#endif
END_OF_FILE
if test 707 -ne `wc -c <'Sources/crack.h'`; then
echo shar: \"'Sources/crack.h'\" unpacked with wrong size!
fi
# end of 'Sources/crack.h'
fi
if test -f 'Sources/speeds.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/speeds.c'\"
else
echo shar: Extracting \"'Sources/speeds.c'\" \(866 characters\)
sed "s/^X//" >'Sources/speeds.c' <<'END_OF_FILE'
X#include <sys/time.h>
X#include <signal.h>
X#include <stdio.h>
X
Xstatic int cnt;
X#define ITIME 10 /* Number of seconds to run test. */
X
Xvoid
XStop ()
X{
X printf ("Did %f %s()s per second.\n",
X ((float) cnt) / ((float) ITIME),
X#if defined(T1)
X "fcrypt"
X#elif defined(T2)
X "xform"
X#else
X "crypt"
X#endif
X );
X exit (0);
X}
Xmain ()
X{
X struct itimerval itv;
X static int quarters[4];
X
X bzero (&itv, sizeof (itv));
X
X printf ("Running for %d seconds of virtual time ...\n", ITIME);
X
X#if defined(T1) || defined(T2)
X init_des ();
X#endif
X
X signal (SIGVTALRM, Stop);
X itv.it_value.tv_sec = ITIME;
X itv.it_value.tv_usec = 0;
X setitimer (ITIMER_VIRTUAL, &itv, NULL);
X
X for (cnt = 0;; cnt++)
X {
X#if defined(T1)
X fcrypt ("fredfred", "eek");
X#elif defined(T2)
X xform (quarters, 0);
X#else
X crypt ("fredfred", "eek");
X#endif
X }
X}
END_OF_FILE
if test 866 -ne `wc -c <'Sources/speeds.c'`; then
echo shar: \"'Sources/speeds.c'\" unpacked with wrong size!
fi
# end of 'Sources/speeds.c'
fi
if test -f 'Sources/tester.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/tester.c'\"
else
echo shar: Extracting \"'Sources/tester.c'\" \(612 characters\)
sed "s/^X//" >'Sources/tester.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <time.h>
X
X#define EEK 8192
X#define PROFx
X
Xmain ()
X{
X int i;
X char a[255];
X char b[255];
X
X init_des ();
X
X#ifndef PROF
X strcpy (a, crypt ("fredfred", "fredfred"));
X strcpy (b, fcrypt ("fredfred", "fredfred"));
X
X printf ("Check Old: %s\tNew: %s\n", a, b);
X
X if (!strcmp (a, b))
X {
X printf ("fcrypt() is compatible with standard crypt()\n");
X } else
X {
X printf ("fcrypt() is not compatible !!! \7\n");
X exit (1);
X }
X printf ("Doing %d fcrypts()\n", EEK);
X#endif
X
X for (i = EEK; i; i--)
X {
X fcrypt ("fredfred", "eek");
X }
X
X return (0);
X}
END_OF_FILE
if test 612 -ne `wc -c <'Sources/tester.c'`; then
echo shar: \"'Sources/tester.c'\" unpacked with wrong size!
fi
# end of 'Sources/tester.c'
fi
echo shar: End of archive 1 \(of 4\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 4 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
exit 0 # Just in case...

Alec David Muffett

unread,
Aug 23, 1991, 11:04:16 AM8/23/91
to
Submitted-by: Alec David Muffett <a...@aber.ac.uk>
Posting-number: Volume 22, Issue 50
Archive-name: crack/part02
Environment: UNIX

#! /bin/sh


# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:

# "End of archive 2 (of 4)."
# Contents: APPENDIX Crack DictSrc/bad_pws.dat Sources/crack-pp.c
# Sources/crack-pwc.c Sources/goodpass.c
# Wrapped by aem@aberda on Fri Aug 23 13:20:41 1991


PATH=/bin:/usr/bin:/usr/ucb ; export PATH

if test -f 'APPENDIX' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'APPENDIX'\"
else
echo shar: Extracting \"'APPENDIX'\" \(12711 characters\)
sed "s/^X//" >'APPENDIX' <<'END_OF_FILE'
XOdds and sods that I thought are interesting:
X
X********
X
XSeveral people have asked me why I don't write Crack so that it
Xdistributes dictionaries over the network and hacks the same password
Xfile on each machine, as opposed to spreading users over the network and
Xusing the same dictionaries.
X
XThere are several reasons for this, which I will outline.
X
XThe reasoning that spreading the dictionaries over the network is faster
Xis correct in the case of cracking the passwords of ONE user - it is
Xmost efficient to run different dictionaries on him on several machines,
Xand you will break his password eventually.
X
XScaling this by a factor of 'n' users causes problems. Firstly, if a
Xmachine guesses one persons password, it must inform all others on the
Xnetwork not to waste time cracking him, but to get on with the other
Xusers. This is difficult and nasty.
X
XSecondly, it is not what Crack was designed to do. The name "Crack" is
Xactually a misnomer - Crack really ought to be called "Passwdcheck" or
Xsomething similar, but such names lack sex appeal.
X
XCrack is not a program designed to break the password of every user in
Xthe file. Rather, it is designed to find weak passwords in the file, by
Xattacking those sorts of bad passwords which are most likely to be used,
Xin the order in which they would most easily be found (ie: are most
Xlikely to be used by a moronic user).
X
XCrack is not designed to break user passwords; it is designed to break
Xpassword files. This is a subtle but important distinction.
X
XIf you want to break into a safe, you do not take a hammer at every bit
Xof it in turn; instead, first you try some simple combinations, then you
Xtry blowing the hinges off, then you get out an acetylene torch and go
Xfor the bolt. If that doesnt work, THEN you start on the walls. You go
Xfor the bits which are most likely to be weak first.
X
XConsider a password file with 'n' users in it. Say that your serial
Xpassword cracker uses a dictionary of 1000 words, and tries each word 6
Xways (upper/lower/mixed case, permuted with forwards/backwards)
X
XAlso consider that out of that 1000 users, only one (the last one) has a
Xguessable password - "fred".
X
XAlso say that it takes time 'T' seconds to encrypt a word.
X
XIf you use the "try each user in turn" method, like the COPS password
Xcracker, you will have to wait for a time:-
X
X 999 users * 1000 words * 6 ways * T = 5994000 T seconds
X
Xbefore you get to that last user. Spreading this load around on a
Xnetwork only alleviates the number of words to be searched (divides them
Xby the number of machines you are working on).
X
XThus, if you use 10 machines, the machine which will guess "fred" will
Xget to that last user in:-
X
X 999 * (1000 / 10) * 6 ways = 599400 T seconds.
X
XAlternatively you can try it the Crack way - "fred" is a word which
Xappears in a forwards dictionary. You will only wait:-
X
X 999 users * 1000 words * 1st way * T = 999000 T seconds
X
Xto get to that user. Now split the _USERS_ across 10 machines:-
X
X (999 / 10) users * 1000 words * 1st way = 99900 T seconds
X
XTo get to his password, in ONLY 17% of the time taken by networking
Xusing the serial cracking method. This is only a boundary case, but I
Xhope I have illustrated the concept.
X
X********
X
XCrack has several other optimisations because of its structured password
Xguesses. The figures below are entirely empirical, but I reckon that
Xthey're as good as any:
X
XThe first pass that Crack makes is over the user data user information
Xgleaned from the users' password field. In my test file, this gets
Xabout 3% of the passwords (out of a total of 11% guessed). This pass
Xalso completes the quickest of all, working as it does from a very small
Xamount of data, but one which is very frequently used for passwords.
X
XMy test password file is 1150 users big, and the first pass completes in
Xa little over 2 minutes. In that time Crack gets 35 accounts.
X
XThe first sweep of the second pass, consisting of lowercase dictionary
Xwords, gets about another 5% of the passwords. This means that, for our
X1150 users, we have now cracked a cumulative total of 91 accounts. The
Xlength of the first sweep depends on how much CPU and how many
Xdictionaries I supply, but using the Ultrix /usr/dict/words and my
Xbad_pws.dat, over 4 CPUs, it doesn't take much more that a couple of
Xhours.
X
XFor the further sweeps, the percentages cracked per sweep tail off, 2%,
X1%, 0.5%... But they are the people with fairly exotic passwords, and
Xit's only common sense that that they will take some time to crack.
X
X********
X
XThere is one more major optimisation that I haven't mentioned. Because
Xof the way the UNIX crypt() algorithm works, each encryption is "salted"
Xwith a two letter sequence which is stored as the first two characters
Xof the encrypted password. This salting means that the word "fred" can
Xbe encrypted and appear in a password file in (literally) thousands of
Xdifferent ways - so long as each encryption has a different salt.
X
XHence, it makes sense to do things in this manner:
X
X1) sort and group the input data by encryption salt.
X2) for each different groups' encryption salt
X * get a dictionary word
X * encrypt it using that salt (This is the time consuming bit)
X * compare the encryption with each member of the group with that salt
X * if it matches, you have guessed that users password.
X
XThis knocks (empirical guesswork time again) up to one third of the
Xdictionary encryptions off - thus saving you 0.3 of the time all the
Xdictionary sweeps would ordinarily take. You can work out this figure
Xyourself: Crack gives this statistic when it says
X
X pwc: Loaded 'n' password entries into 'm' salted lines.
X
Xso you can work out the percentage of users who have the same salt:-
X
X x = (m / n) * 100
X
Xand hence the percentage of encryption time that you save = (100 - x).
X
X********
X
XListening to the REM album 'Green' on the way back from the Cropredy
Xfolk festival yesterday, whilst I was thinking over things to do to
XCrack, and I was struck (not for the first time) by the words of the
Xfirst verse to 'World Leader Pretend':-
X
X I sit at my table, and wage war upon myself.
X It seems like it's all, it's all for nothing.
X I know the barricades, and I know the mortar in the wall
X I recognise the weapons, I use them well.
X
X This is my mistake, let me make it good,
X I raised the wall, and I will be the one to knock it down...
X
X- writing password cracking programs gets to you after a bit.
X
X********
X
XSome people have asked me how to generate safe passwords. This, sadly,
Xhas become a religious issue, and there are now, on USENET, several
Xvociferous "password geeks" who will say "my method is the best", in the
Xsame way that some mathematicians will try to compare so-called "random
Xnumber generating algorithms". Such statements are pointless. I'm
Xsorry for adding to the confusion, but I must say that I think they are
Xwrong.
X
XOkay, so I am a security fatalist and a security philosopher, but I am
Xnot going to give and hard and fast answers; rather, I'd like to make
Xsome points and recommendations to the people out there. Security isn't
Xa tangible thing, it is applied psychology.
X
XThe whole point of a password is to prevent people accessing your
Xsystem, getting into it from outside. Once someone is inside your
Xsystem, assuming that they have the relevant knowledge of your O/S, it
Xis safest to assume that anyone can get to be 'superuser'. Your only
Xsecurity once someone is on your system is called "security by
Xobscurity". If your user has sufficient knowledge, you've "had it".
X
XThe question isn't "How secure can my system be made?".
X
XThe question really should be, "How much do I care, how much can I trust?".
X
XA system can be perfectly secure without any passwords at all, so long
Xas it is in an environment of people who recognise its purpose and
Xdepend on it. I say this after having had acounts on several 'public'
Xmachines, which could have been taken to bits by any competent Unix
Xperson, but were largely safe - because when someone worked out who did
Xanything nasty, the culprit was ostracised from the community. There
X_is_ a caveat to this, however.
X
XThe problem is the sort of people who go around the world 'collecting'
Xcomputer accounts and breaking machines, those who have either a
Xchildish mentality or an ulterior motive.
X
XThe former are like the little boys who go around breaking windows and
Xvandalising things 'for kicks'. They are the ones who see every
Xpassword file as a "NO ENTRY" sign, and therefore, driven by what they
Xthink is anarchy and fun, they break in and smash the place up. Tell
Xthem that they are behaving like children, and they will behave moreso.
X
XThe latter are driven by personal motives or money. Their reasons are
Xtoo complex for me to analyse here.
X
XThe 'babyish' hackers need a lesson (which I hope that eventually they
Xlearn) that true anarchy is for the general good, and is best achieved
Xby fiat amongst the community. USENET is a good example - there is a
Xlot of petty bickering and arguing, but an incredible amount of good
Xcomes out of it. It is anarchy that the old greek philosophers would
Xhave approved of.
X
XWhat I am trying to say is that, when I say that if someone gets into
Xyour system, you've "had it", you should consider whether there is
Xanything to have "had" in the first place. There is no point in getting
Xyourself paranoid over security - if you do, you'll lose out. Don't be
Xtoo paranoid. Be SENSIBLE instead, and secure your system according to
Xit's needs, and not according to some 'holy bible' of absolute security.
X
XIf someone gets into your system, you find out how they did it, patch
Xthe hole, check for back doors, brush yourself off, and start again.
XIt's not the end of the world.
X
XWhat this statement doesn't address (yet) is the needs of system
Xmanagers who have a REAL need for security - be it corporate data or
Xresearch work - on their system. As I have said before, most O/S's have
Xgaping holes in them that cannot be entirely filled, and so the users
Xmust be stopped on the doorstep. At the password login.
X
XPeople who say that they have a way of generating safe passwords are
Xmisinformed, IMHO. Saying that the password "wyufwqpl" is secure is as
Xmeaningful as saying that the number "4" is random. Password security,
Xlike any other form of computer security, is not an absolute, but should
Xbe taken in context.
X
XYou can't say that a certain method will provide secure, random
Xpasswords, because, in defining an algorithm to create these passwords,
Xyou will use only a subset of all the possible passwords that could ever
Xexist. You have shrunk the 'search space' for the passwords.
X
XSomeone merely has to write a password cracker which will search this
Xsmall subset of passwords, in order to break your system. Passwords
Xgenerated by any algorithm, human or computer based, are merly
Xpseudo-secure, in the same way that numbers can be pseudo-random. For
Xillustration of this aspect of password security, read the document
X"Password Security, A Case History" by Morris and Thompson.
X
XThere is an incredibly large set of possible passwords in the world, and
Xthe best approach toward choosing a password is not to try to find a way
Xto generate 'secure' passwords - there are no such things - but rather
Xyou should learn to choose passwords which are not easily searched for.
XPasswords which are out of the 'search space' of most password crackers
Xlike 'Crack'.
X
XRead the Crack documentation. See what sort of things other programs
Xlike Crack would search for. Think of some yourself. I am not going to
Xspecifically mention methods, you should really work something out for
Xyourself.
X
XAt the bottom line, the password "fred" is just as secure (random) as
Xthe password "blurflpox"; the only problem is that "fred" is in a more
Xeasily searched part of the "password space".
X
XBoth of these passwords are more easily found than "Dxk&2+15^N" however.
XNow you must ask yourself if you can cope with remembering "Dxk&2+15^N".
X
X8-)
X
X********
X
XI'd like to thank Chris Samuel & Piercarlo (Peter) Grandi for all their
Xhelp in beta-testing Crack, and in Peter's case especially, for dropping
Xme into the deep end of troff. Die, you bastard. 8->
X
XI'd also like to thank Chris Myers for giving me an archive site to work
Xfrom (saving me a lot of tedious email) and heaps of suggestions.
X
XSimilarly for Randal Schwartz for his information and Chris Lewis (the
Xpsroff guy) for all his suggestions.
X - alec


X--
XINET: a...@aber.ac.uk JANET: a...@uk.ac.aber BITNET: aem%aber@ukacrl
XUUCP: ...!mcsun!ukc!aber!aem ARPA: aem%uk.ac...@nsfnet-relay.ac.uk
XSNAIL: Alec Muffett, Computer Unit, Llandinam UCW, Aberystwyth, UK, SY23 3DB
END_OF_FILE

if test 12711 -ne `wc -c <'APPENDIX'`; then
echo shar: \"'APPENDIX'\" unpacked with wrong size!
fi
# end of 'APPENDIX'
fi
if test -f 'Crack' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Crack'\"
else
echo shar: Extracting \"'Crack'\" \(3891 characters\)
sed "s/^X//" >'Crack' <<'END_OF_FILE'
X#!/bin/csh


X
X###
X# This program written by ADE Muffett (a...@aber.ac.uk), August 1991,
X# as part of the 'Crack' password cracking package.
X###
X
X###

X# You must put DOUBLE QUOTES around this is you work relative to ~username
X###
X
Xsetenv CRACK_HOME "~aem/SEC/CRACK32"
X
Xset trash="/dev/null"
Xset remote="FALSE"
Xset default_bin="generic"
Xset tmpfile="/tmp/cpwfs.$$"
Xset net_cf="Scripts/network.conf"


X
X###
X# Check existance of a home directory
X###
X

Xif ( -d $CRACK_HOME ) then


X cd $CRACK_HOME || exit 1
Xelse
X echo "Error: The directory $CRACK_HOME does not exist."
X echo ""
X echo "Please set the value of CRACK_HOME in the Crack script to the CRACK31"
X echo "installation directory."
X echo ""
X echo "The current working directory is" `pwd`
X exit 1

Xendif


X
X###
X# Announce ourselves.
X###
X
Xecho "Crack 3.2a Password Cracker by ADE Muffett, 1991"
X
X###
X# Check that we have arguments
X###
X

Xif ( "$1" == "" ) then


X echo "Usage: $0 [options] [bindir] passwdfile [...]"
X echo "Or: $0 -network [options] passwdfile [...]"
X echo "With options:-"
X echo " -v - to produce verbose output (if configured)"
X echo " -nnicevalue - to run niced"
X echo " -rpointfile - to recover a crashed-out job"
X echo " -Rpointfile - to recover (with verify) a crashed-out job"
X exit 1

Xendif


X
X###
X# Parse command line
X###
X

Xset argl=()
X
Xwhile ( 1 )
X switch ( $1 )
X case -network: # push onto the remote machines
X if ( ! -f $net_cf ) then


X echo "$0: error: no file $net_cf"
X exit 1

X endif


X shift
X Scripts/Crack.network $*
X exit 0

X breaksw # redundant
X case -remote: # This is being called remotely


X echo "Invoked: $0 $*"
X set remote="TRUE"
X shift

X breaksw
X case -v*: # verbose
X case -n*: # nice
X case -r*: # recover
X case -R*: # recover/verify
X set argl=($argl $1)
X shift
X breaksw
X case -*: # anything else


X echo "Crack: unknown argument $1"
X shift

X breaksw
X default:
X break
X breaksw # redundant
X endsw
Xend


X
X###
X# Test first non-switch argument for existance
X###
X

Xif ( -f "$1" ) then
X setenv CRACK_ARCH $CRACK_HOME/$default_bin
X if ( ! -d $default_bin ) then


X echo "Making default binary directory: $default_bin"
X mkdir $default_bin || exit 1

X endif
Xelse if ( -d "$1" ) then
X setenv CRACK_ARCH $CRACK_HOME/$1


X shift
Xelse
X echo "Crack: error: There is no directory or file $1."
X echo "Crack: warning: Creating directory $1"
X mkdir $1 || exit 1

X setenv CRACK_ARCH $CRACK_HOME/$1
X shift
Xendif


X
X###
X# Double check the dictionary directory
X###
X

Xif ( ! -d $CRACK_HOME/Dicts ) then


X echo "Crack: error: There is no directory or file Dicts."
X echo "Crack: warning: Creating directory Dicts"
X mkdir Dicts || exit 1

Xendif


X
X###
X# Now to tidy up a bit
X###
X

Xmake -f Scripts/crack.mf cleanprogs >& /dev/null


X
Xecho "Using binaries in directory: $CRACK_ARCH"
X

Xcd $CRACK_ARCH || exit 1 # Can we get there from here ?


X
X###
X# Install makefiles if necessary.
X###
X

Xif ( ! -f Makefile ) then # Has it a Makefile ?
X cp $CRACK_HOME/Scripts/install.mf Makefile
Xendif
X
Xmake crack-pwc || exit 1 # Check binaries are OK
X
Xcd $CRACK_HOME # Get back to home base
X
Xmake -f Scripts/crack.mf dictstamp || exit 1 # Make the dictionaries


X
X###
X# Check how we have been invoked : ergo how we get our data.
X###
X

Xif ( "$remote" == "TRUE" ) then
X cat > $tmpfile # Use stdin
Xelse
X Scripts/joinfiles $* > $tmpfile || exit 1 # Process the passwords
Xendif


X
Xecho "Backgrounding program. Output will be written to a file in this directory."
X

X$CRACK_ARCH/crack-pwc $argl -i$tmpfile Dicts/dict.* < /dev/null >& $trash &


X
X###
X# There are horrible timeraces involved in removing $tmpfile, so I dont.
X###
END_OF_FILE

if test 3891 -ne `wc -c <'Crack'`; then
echo shar: \"'Crack'\" unpacked with wrong size!
fi
chmod +x 'Crack'
# end of 'Crack'
fi
if test -f 'DictSrc/bad_pws.dat' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'DictSrc/bad_pws.dat'\"
else
echo shar: Extracting \"'DictSrc/bad_pws.dat'\" \(6485 characters\)
sed "s/^X//" >'DictSrc/bad_pws.dat' <<'END_OF_FILE'
X0
X1
X123456
X12345678
X2
X3
X4
X5
X6
X7
X8
X9
XA
XAdrian
XAdrianna
XAlasdair
XAlbert
XAlex
XAlexander
XAlice
XAlicia
XAlisa
XAlison
XAlistair
XAlister
XAllison
XAmanda
XAmber
XAmy
XAndrea
XAnduin
XAngela
XAngie
XAnita
XAnn
XAnna
XAnne
XAnnette
XApril
XArlene
XArthur
XAthena
XB
XBBROYGBVGW
XBailey
XBarbara
XBart
XBartman
XBecky
XBeryl
XBeth
XBetsie
XBetty
XBeverly
XBishop
XBob
XBrandi
XBrandy
XBrenda
XBridget
XC
XCalvin
XCamille
XCandi
XCandy
XCaren
XCarla
XCarmen
XCarol
XCarole
XCarolina
XCaroline
XCarrie
XCatherine
XCathy
XCecily
XCharity
XCharles
XChristina
XChristine
XChristy
XCindy
XClaudia
XCollins
XConnie
XCornelius
XCristina
XCrystal
XCynthia
XD
XDaisy
XDana
XDaniel
XDanielle
XDawn
XDeb
XDebbie
XDeborah
XDenise
XDesiree
XDiana
XDiane
XDoobrie
XDulce
XDuncan
XE
XEdwina
XEileen
XEinstein
XElaine
XElanor
XElizabeth
XEllen
XEmily
XEmmanuel
XErica
XErika
XErin
XEvelyn
XF
XFelicia
XG
XGabriel
XGeorge
XGertrude
XGilly
XGina
XGinger
XH
XHarvey
XHeather
XHeidi
XHiawatha
XHobbes
XHolly
XI
XIngrid
XIrene
XJ
XJackie
XJane
XJanet
XJanice
XJanie
XJasmin
XJean
XJeanne
XJen
XJenni
XJennifer
XJenny
XJessica
XJill
XJoanne
XJody
XJohnny
XJoseph
XJoshua
XJoy
XJoyce
XJudith
XJudy
XJulia
XJulie
XJune
XK
XKaren
XKarie
XKarina
XKate
XKathleen
XKathrine
XKathy
XKatina
XKatrina
XKelly
XKeri
XKerri
XKerrie
XKerry
XKim
XKimberly
XKitten
XKrista
XKristen
XKristi
XKristie
XKristin
XKristine
XKristy
XL
XLana
XLara
XLaura
XLeah
XLeslie
XLinda
XLisa
XLiz
XLois
XLori
XLorin
XLorraine
XLouis
XLouise
XLucy
XLynn
XLynne
XM
XMVEMJSUNP
XMalcolm
XMara
XMarci
XMarcy
XMaria
XMarietta
XMarni
XMary
XMaurice
XMeagan
XMegan
XMelissa
XMichael
XMichele
XMichelle
XMickey
XMonica
XMortis
XN
XNancy
XNicole
XNita
XNoreen
XO
XOlivia
XP
XPam
XPamela
XPat
XPatricia
XPatty
XPaula
XPenelope
XPierre
XPolly
XQ
XR
XRachel
XRachelle
XRebecca
XRenee
XRobin
XRobyn
XRochelle
XRonald
XRonnie
XRose
XRosemary
XS
XSamantha
XSandra
XSandy
XSara
XSarah
XShannon
XSharon
XSherri
XShirley
XSnarfel
XSondra
XSonia
XSonya
XStacey
XStaci
XStacie
XStacy
XSteph
XStephanie
XSusan
XSusanne
XSusie
XSuzanne
XSuzie
XSybil
XT
XTamara
XTami
XTamie
XTammy
XTara
XTheresa
XTiffany
XTina
XTraci
XTracie
XTracy
XTrisha
XU
XUrsula
XV
XValerie
XVeronica
XVicky
XVirginia
XW
XWOBAFGKMRNS
XWarren
XWendi
XWendy
XWhitney
XWilliam
XWillie
XWilma
XX
XY
XYolanda
XZ
Xa
Xaaa
Xabc
Xabcd
Xabcde
Xabcdef
Xabcdefg
Xabcdefgh
Xacademia
Xacademic
Xaccess
Xada
Xadmin
Xaerobics
Xairplane
Xalbany
Xalbatross
Xalf
Xalgebra
Xalias
Xaliases
Xalpha
Xalphabet
Xama
Xamadeus
Xamorphous
Xanalog
Xanchor
Xandromache
Xandy
Xanimals
Xanswer
Xanthropogenic
Xanvils
Xanything
Xaria
Xariadne
Xarrow
Xasd
Xasdfgh
Xasm
Xasshole
Xatmosphere
Xaztecs
Xazure
Xb
Xbacchus
Xbadass
Xbanana
Xbananas
Xbandit
Xbanks
Xbarber
Xbaritone
Xbasic
Xbass
Xbassoon
Xbatch
Xbatman
Xbeach
Xbeater
Xbeauty
Xbeaver
Xbeethoven
Xbeetledrive
Xbeloved
Xbenz
Xbeowulf
Xberkeley
Xberlin
Xberliner
Xbeta
Xbicameral
Xbitch
Xbizzy
Xbradley
Xbrian
Xbroadway
Xbsd
Xbuggerall
Xbumbling
Xburgess
Xbuzby
Xc
Xcad
Xcampanile
Xcantor
Xcardinal
Xcarmen
Xcarolina
Xcarson
Xcascades
Xcastle
Xcat
Xcayuga
Xceltics
Xcerulean
Xchange
Xcharles
Xcharming
Xcharon
Xchat
Xcheesecake
Xchem
Xchemistry
Xchess
Xchester
Xchocolate
Xcigar
Xcinelli
Xclass
Xclassic
Xcluster
Xclusters
Xcode
Xcoffee
Xcoke
Xcollins
Xcommrades
Xcomputer
Xcomrade
Xcomrades
Xcondo
Xcondom
Xconnect
Xconsole
Xcookie
Xcookie
Xcooper
Xcornelius
Xcouscous
Xcreate
Xcreation
Xcreosote
Xcretin
Xcriminal
Xcshrc
Xd
Xdaemon
Xdancer
Xdaniel
Xdanny
Xdapper
Xdata
Xdave
Xdecember
Xdefault
Xdefoe
Xdeluge
Xdesperate
Xdevelop
Xdevice
Xdial
Xdiet
Xdieter
Xdigital
Xdisc
Xdiscbox
Xdiscovery
Xdisk
Xdisney
Xdog
Xdos
Xdrought
Xe
Xeager
Xearth
Xeasier
Xeasy
Xeatme
Xedges
Xedinburgh
Xedwin
Xegghead
Xeiderdown
Xelephant
Xemail
Xemerald
Xenemy
Xengine
Xengineer
Xenterprise
Xenzyme
Xersatz
Xestablish
Xestate
Xeternity
Xeuclid
Xeugene
Xextension
Xf
Xfairway
Xfender
Xfermat
Xferrari
Xfidelity
Xfield
Xfile
Xfinite
Xfishers
Xflakes
Xfloat
Xflower
Xflowers
Xfoolproof
Xfootball
Xforesight
Xformat
Xforsythe
Xfourier
Xfred
Xfriend
Xfrighten
Xfun
Xfunction
Xfungible
Xg
Xgabriel
Xgames
Xgardner
Xgarfield
Xgatt
Xgauss
Xgeorge
Xgertrude
Xgibson
Xglacier
Xgnu
Xgolf
Xgolfer
Xgorgeous
Xgorges
Xgosling
Xgouge
Xgraham
Xgrahm
Xgrass
Xgroup
Xgryphon
Xgucci
Xguess
Xguest
Xguitar
Xgumption
Xguntis
Xgweledigaeth
Xh
Xhack
Xhacker
Xhal
Xhamlet
Xhandily
Xhappening
Xharmony
Xharold
Xhawaii
Xhebrides
Xheinlein
Xhello
Xhelp
Xherbert
Xhibernia
Xhidden
Xhobbit
Xhomework
Xhoney
Xhorse
Xhorus
Xhutchins
Xhydrogen
Xibm
Xiluvben
Ximbroglio
Ximperial
Xinclude
Xingres
Xingress
Xinna
Xinnocuous
Xinternet
Xirishman
Xisis
Xizzy
Xj
Xjapan
Xjester
Xjixian
Xjohnny
Xjuggle
Xjupiter
Xk
Xkalajira
Xkermit
Xkernel
Xkey
Xkipper
Xkirkland
Xknight
Xl
Xladle
Xlager
Xlambda
Xlamination
Xlarkin
Xlarry
Xlazarus
Xlebesgue
Xlee
Xleland
Xleroy
Xlewis
Xlibrary
Xlight
Xlisp
Xllareggub
Xlock
Xlockout
Xlove
Xm
Xmacintosh
Xmack
Xmaggot
Xmagic
Xmail
Xmaint
Xmalcom
Xmanager
Xmark
Xmarkus
Xmars
Xmarty
Xmarvin
Xmaster
Xmath
Xmaurice
Xmellon
Xmemory
Xmercury
Xmerlin
Xmets
Xmgr
Xmichael
Xmike
Xminimum
Xminsky
Xmit
Xmodem
Xmogul
Xmoguls
Xmoose
Xmorley
Xmortis
Xmouse
Xmozart
Xmuser
Xmutant
Xn
Xnagel
Xnapoleon
Xnasa
Xnepenthe
Xneptune
Xness
Xnet
Xnetwork
Xnew
Xnews
Xnewton
Xnext
Xnobody
Xnoxious
Xnuclear
Xnutrition
Xnyquist
Xo
Xoceanography
Xocelot
Xoerhrdle
Xoffice
Xolivetti
Xolivia
Xopen
Xoperator
Xoracle
Xorca
Xorchid
Xorwell
Xosiris
Xoutlaw
Xoxford
Xp
Xpacific
Xpad
Xpainless
Xpakistan
Xpaper
Xpapers
Xpass
Xpassword
Xpencil
Xpenguin
Xpenis
Xpeoria
Xpercolate
Xpersimmon
Xpersona
Xpete
Xpeter
Xphilip
Xphoenix
Xphone
Xpierre
Xpizza
Xplane
Xplayboy
Xplover
Xpluto
Xplymouth
Xpolynomial
Xpondering
Xpork
Xporsche
Xposter
Xpower
Xpraise
Xprecious
Xprelude
Xpresto
Xprince
Xprinceton
Xpriv
Xprivate
Xprivs
Xprofessor
Xprofile
Xprogram
Xprotect
Xprotozoa
Xpub
Xpublic
Xpumpkin
Xpuneet
Xpuppet
Xq
Xqwerty
Xqwertyui
Xr
Xrabbit
Xrachmaninoff
Xrainbow
Xraindrop
Xraleigh
Xrandom
Xrascal
Xreagan
Xreally
Xregional
Xremote
Xrick
Xripple
Xrisc
Xrje
Xrobot
Xrobotics
Xrochester
Xrodent
Xrolex
Xromano
Xronald
Xroot
Xrosebud
Xroses
Xruben
Xrules
Xruth
Xs
Xsal
Xsaturn
Xsaxon
Xscamper
Xscheme
Xschool
Xscott
Xscotty
Xsecret
Xsecurity
Xsensor
Xserenity
Xservice
Xsesame
Xsex
Xsharc
Xsharks
Xsharon
Xsheffield
Xsheldon
Xshell
Xshit
Xshitforbrains
Xshiva
Xshivers
Xshuttle
Xsignature
Xsilverlake
Xsimon
Xsimple
Xsimpsons
Xsinger
Xsingle
Xsmile
Xsmiles
Xsmooch
Xsmother
Xsnatch
Xsnoopy
Xsoap
Xsocrates
Xsomebody
Xsossina
Xsparrows
Xspit
Xsplatter
Xsplodge
Xspring
Xspringer
Xsquires
Xstrangle
Xstratford
Xstudent
Xstuttgart
Xsubway
Xsuccess
Xsucker
Xsummer
Xsun
Xsuper
Xsuperstage
Xsuperuser
Xsupport
Xsupported
Xsurfer
Xswearer
Xsymmetry
Xsys
Xsysadmin
Xsystem
Xt
Xtangerine
Xtape
Xtarget
Xtarragon
Xtaylor
Xteabag
Xtech
Xtelephone
Xtemptation
Xtennis
Xterminal
Xtest
Xthailand
Xthanatos
Xtiger
Xtoggle
Xtomato
Xtopography
Xtortoise
Xtoxic
Xtoyota
Xtrails
Xtransfer
Xtrivial
Xtrombone
Xtty
Xtubas
Xtuttle
Xu
Xumesh
Xunhappy
Xunicorn
Xunix
Xunknown
Xuranus
Xurchin
Xutil
Xutility
Xuucp
Xv
Xvasant
Xvenus
Xvertigo
Xvillage
Xvirgin
Xvisitor
Xvortex
Xw
Xwargames
Xwarren
Xwater
Xweenie
Xwhatever
Xwhatnot
Xwhiting
Xwhitney
Xwholesale
Xwill
Xwilliam
Xwilliamsburg
Xwillie
Xwinston
Xwisconsin
Xwizard
Xwizzy
Xwombat
Xwoodwind
Xword
Xwork
Xwormwood
Xwyoming
Xx
Xxerox
Xxfer
Xxmodem
Xxyz
Xy
Xyaco
Xyang
Xyellowstone
Xyosemite
Xz
Xzap
Xzerox
Xzimmerman
Xzmodem
Xzxcvbn
END_OF_FILE
if test 6485 -ne `wc -c <'DictSrc/bad_pws.dat'`; then
echo shar: \"'DictSrc/bad_pws.dat'\" unpacked with wrong size!
fi
# end of 'DictSrc/bad_pws.dat'
fi
if test -f 'Sources/crack-pp.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack-pp.c'\"
else
echo shar: Extracting \"'Sources/crack-pp.c'\" \(4025 characters\)
sed "s/^X//" >'Sources/crack-pp.c' <<'END_OF_FILE'


X#include "crack.h"
X
X/*
X * This program is copyright (c) Alec Muffett 1991 except for certain
X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
X * Sparry and Alec Muffett. The author(s) disclaims all responsibility or
X * liability with respect to it's usage or its effect upon hardware or
X * computer systems. This software is in the public domain and is freely
X * redistributable PROVIDED that this notice remains intact.
X */
X
X

X/* THIS IS THE STRING TO MODIFY TO ADD OTHER LEADING/TRAILING CHARS */
X
Xchar trailing_chars[] = "01";
X
X/* These used to be enums. Oh well... non-portability rules OK */
X#define ORDER_LCF 0
X#define ORDER_LCFP 1
X#define ORDER_MCF 2
X#define ORDER_LCB 3
X#define ORDER_LCFT 4
X#define ORDER_UCF 5
X#define ORDER_UCB 6
X#define ORDER_MCB 7
X#define NUMFILES 8
X
Xint
Xmain (argc, argv)
X int argc;
X char *argv[];


X{
X register int i;

X register char *ptr;
X int length;
X int all_digits;
X int all_letters_upper;
X int all_letters_lower;
X char buffer[STRINGSIZE];
X
X FILE *fp;
X FILE *fps[NUMFILES];
X
X if (argc == 1)
X {
X printf ("Usage:\t%s dictsrc [dictsrc ...]\n", argv[0]);
X exit (1);
X }
X for (i = 0; i < NUMFILES; i++)
X {
X char scratch[255];
X
X fps[i] = (FILE *) 0;
X#ifndef CRACK_PLURAL /* if not defined, skip opening it */
X if (i == ORDER_LCFP)
X {
X continue;
X }
X#endif /* CRACK_PLURAL */
X#ifndef CRACK_TRAILING /* if not defined, skip opening it */
X if (i == ORDER_LCFT)
X {
X continue;
X }
X#endif /* CRACK_TRAILING */
X sprintf (scratch, "dict.%c", i + 'a');
X if (!(fps[i] = fopen (scratch, "w")))
X {
X perror (scratch);
X exit (3);
X }
X }
X
X for (i = 1; argv[i]; i++)
X {
X if (!(fp = fopen (argv[i], "r")))
X {
X perror (argv[i]);
X exit (1);
X }
X printf ("dictpp: sourcing from file '%s'\n", argv[i]);
X
X while (fgets (buffer, STRINGSIZE, fp))
X {
X Trim (buffer);
X
X /* skip single letters and comments*/
X if (!*buffer || !buffer[1] || buffer[0] == '#')
X {
X continue;
X }
X length = strlen (buffer);
X#ifndef CRACK_SHORT_PASSWDS
X if (length < 5)
X {
X continue;
X }
X#endif
X all_letters_upper = 1;
X all_letters_lower = 1;
X all_digits = 1;
X
X for (ptr = buffer; *ptr; ptr++)
X {
X if (!isdigit (*ptr))
X {
X all_digits = 0;
X }
X if (isupper (*ptr))
X {
X all_letters_lower = 0;
X } else if (islower (*ptr))
X {
X all_letters_upper = 0;
X }
X }
X
X if (all_digits)
X {
X fprintf (fps[ORDER_LCF], "%.8s\n", buffer);
X continue; /* hehehehehe */
X }
X if (!all_letters_upper)
X {
X fprintf (fps[ORDER_UCF], "%.8s\n", Uppercase (buffer));
X fprintf (fps[ORDER_UCB], "%.8s\n", Uppercase (Reverse (buffer)));
X } else
X {
X fprintf (fps[ORDER_UCF], "%.8s\n", buffer);
X fprintf (fps[ORDER_UCB], "%.8s\n", Reverse (buffer));
X }
X
X if (!all_letters_lower)
X {
X fprintf (fps[ORDER_LCF], "%.8s\n", Lowercase (buffer));
X fprintf (fps[ORDER_LCB], "%.8s\n", Lowercase (Reverse (buffer)));
X } else
X {
X fprintf (fps[ORDER_LCF], "%.8s\n", buffer);
X fprintf (fps[ORDER_LCB], "%.8s\n", Reverse (buffer));
X#ifdef CRACK_PLURAL
X /* PLURALISATION */
X if (length < 8 && buffer[length - 1] != 's')
X {
X /*
X * Fix suggested by Jim Mattson (mat...@cs.ucsc.edu):-
X * we should not pluralise anything more than 7 chars
X * long, as it is a waste.
X */
X fprintf (fps[ORDER_LCFP], "%.7ss\n", buffer);
X }


X#endif /* CRACK_PLURAL */
X

X#ifdef CRACK_TRAILING
X /* NUMERALISATION */
X if (length < 8)
X {
X for (ptr = trailing_chars; *ptr; ptr++)
X {
X fprintf (fps[ORDER_LCFT], "%.7s%c\n", buffer, *ptr);
X fprintf (fps[ORDER_LCFT], "%c%.7s\n", *ptr, buffer);
X }
X }


X#endif /* CRACK_TRAILING */
X }
X

X if (!all_letters_lower && !all_letters_upper)
X {
X fprintf (fps[ORDER_MCF], "%.8s\n", buffer);
X fprintf (fps[ORDER_MCB], "%.8s\n", Reverse (buffer));
X }
X }
X fclose (fp);
X }
X
X for (i = 0; i < NUMFILES; i++)
X {
X if (fps[i])
X {
X fclose (fps[i]);
X }
X }
X}
END_OF_FILE
if test 4025 -ne `wc -c <'Sources/crack-pp.c'`; then
echo shar: \"'Sources/crack-pp.c'\" unpacked with wrong size!
fi
# end of 'Sources/crack-pp.c'
fi
if test -f 'Sources/crack-pwc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack-pwc.c'\"
else
echo shar: Extracting \"'Sources/crack-pwc.c'\" \(17109 characters\)
sed "s/^X//" >'Sources/crack-pwc.c' <<'END_OF_FILE'
X#include "crack.h"
Xchar version[] = "3.2a"; /* version of prog */
X
X/*


X * This program is copyright (c) Alec Muffett 1991 except for certain
X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
X * Sparry and Alec Muffett. The author(s) disclaims all responsibility or
X * liability with respect to it's usage or its effect upon hardware or
X * computer systems. This software is in the public domain and is freely
X * redistributable PROVIDED that this notice remains intact.
X */
X

X/*
X * crack-pwc.c - an optimised password cracker. (c) ADE Muffett, July 1991.
X * Totally rewritten from an 'standard' password cracker that had been
X * floating about on ther network. Apart from the entire re-write, to save my
X * sanity, this thing orders passwords to minimise calls to crypt(). Use
X * fcrypt() where you have it.
X */
X
X/* Structure definitions */
X
Xstruct USER_ENTRY
X{
X int done;
X char *filename;
X struct passwd passwd;
X struct USER_ENTRY *across;
X struct USER_ENTRY *next;
X};
X
Xstruct DICT_ENTRY
X{
X char *word;
X struct DICT_ENTRY *next;
X};
X/* Variable declarations */
X
Xstruct USER_ENTRY *user_root; /* root of the USER linked list */
X
Xint verify_recover; /* we will doublecheck usernames on recovery */
Xint recover_bool; /* we are trying to recover from a crash */
Xint rpid; /* pid we are recovering */
Xint rusercount; /* count of user we are recovering at;
X * strictly, this is the line of the user we
X * are recovering */
Xchar rdict[STRINGSIZE]; /* dict we are recovering */
Xchar rusername[STRINGSIZE]; /* username we are recovering */
X#ifdef CRACK_NETWORK
Xchar rhostname[STRINGSIZE]; /* hostname we are recovering on */
X#endif
X
Xint verbose_bool; /* is verbose switched on ? */
X
Xint pid; /* pid of parent process */
Xchar opfile[STRINGSIZE]; /* name of output file */
Xchar diefile[STRINGSIZE]; /* name of diefile */
Xchar pointfile[STRINGSIZE]; /* name of pointfile */
X
X#ifdef CRACK_NETWORK
Xchar hostname[STRINGSIZE];
X#endif
X
X/*
X * DIDDY LITTLE USEFUL FUNCTIONS
X */
X
Xvoid
XLog (fmt, a, b, c, d, e, f, g, h, i, j)
X char *fmt;
X{
X long t;
X
X time (&t);
X printf ("pwc: %-15.15s ", ctime (&t) + 4);
X printf (fmt, a, b, c, d, e, f, g, h, i, j);
X fflush (stdout);
X}
X
Xvoid
XCatchTERM ()
X{
X /* bury magnets */
X Log ("Caught a SIGTERM! Commiting suicide...\n");
X /* swallow the rapture */
X Log ("<argh!>\n");
X /* let's gather feathers */
X sync ();
X /* don't fall on me */
X exit (0);
X}
X
Xvoid
XSetPoint (dict, usernumber, username) /* Sets the pointfile up */
X char *dict;
X int usernumber;
X char *username;
X{
X FILE *fp;
X
X if (!(fp = fopen (pointfile, "w")))
X {
X perror (pointfile);
X return;
X }
X#ifdef CRACK_NETWORK
X fprintf (fp, "%s\n", hostname);
X#endif
X fprintf (fp, "%d\n", pid);
X fprintf (fp, "%s\n", dict);
X fprintf (fp, "%d\n", usernumber);
X fprintf (fp, "%s\n", username);
X fclose (fp);
X}
X
Xint /* returns 0 if OK, -1 if not recovering */
XGetPoint (pf)
X char *pf;
X{
X FILE *fp;
X char buffer[STRINGSIZE];
X
X if (!(fp = fopen (pf, "r")))
X {
X perror (pf);
X return (-1);
X }
X#ifdef CRACK_NETWORK
X if (!fgets (buffer, STRINGSIZE, fp)) /* Get the hostname */
X {
X fprintf (stderr, "get hostname flopped\n");
X return (-1);
X }
X Trim (buffer);
X
X if (strcmp (buffer, hostname)) /* Not running on original host */
X {
X fprintf (stderr, "cmp hostname flopped\n");
X return (-1);
X }
X strcpy (rhostname, buffer);
X#endif
X
X if (!fgets (buffer, STRINGSIZE, fp)) /* Get the pid */
X {
X fprintf (stderr, "get pid flopped\n");
X return (-1);
X }
X Trim (buffer);
X rpid = atoi (buffer);
X
X if (!fgets (buffer, STRINGSIZE, fp)) /* Get the dictname */
X {
X fprintf (stderr, "get dict flopped\n");
X return (-1);
X }
X Trim (buffer);
X strcpy (rdict, buffer);
X
X if (!fgets (buffer, STRINGSIZE, fp))
X {
X fprintf (stderr, "get usercount flopped\n");
X return (-1);
X }
X Trim (buffer);
X rusercount = atoi (buffer); /* Get the usernumber to recover */
X
X if (!fgets (buffer, STRINGSIZE, fp)) /* Get the username */
X {
X fprintf (stderr, "get username flopped\n");
X return (-1);
X }
X Trim (buffer);
X strcpy (rusername, buffer);
X
X fclose (fp);
X return (0);
X}
X/*
X * STRUCTURE SPECIFIC FUNCTIONS
X */
X
Xchar *
XPWSkip (p) /* jump the ':' in a pwent */
X register char *p;
X{
X while (*p && *p != ':')
X {
X p++;
X }
X if (*p)
X {
X *p++ = '\0';
X }
X return (p);
X}
X
Xstruct USER_ENTRY *
XParse (buffer) /* break up input into a structure */
X register char *buffer;
X{
X register char *p;
X register struct USER_ENTRY *retval;
X
X retval = (struct USER_ENTRY *) malloc (sizeof (struct USER_ENTRY));
X retval -> next = retval -> across = NULL;
X retval -> done = 0;
X Trim (buffer);
X
X p = Clone (buffer);
X retval -> filename = p;
X p = PWSkip (p);
X retval -> passwd.pw_name = p;
X p = PWSkip (p);
X retval -> passwd.pw_passwd = p;
X p = PWSkip (p);
X retval -> passwd.pw_uid = 1;
X p = PWSkip (p);
X retval -> passwd.pw_gid = 1;
X p = PWSkip (p);
X retval -> passwd.pw_gecos = p;
X p = PWSkip (p);
X retval -> passwd.pw_dir = p;
X p = PWSkip (p);
X retval -> passwd.pw_shell = p;
X return (retval);
X}
X/*
X * START OF MODULES
X */
X
Xvoid
XLoadData () /* load sorted entries into memory */
X{
X char *ptr;
X char salt[2];
X char buffer[STRINGSIZE];
X int numlines;
X int numentries;
X register struct USER_ENTRY *new_element;
X register struct USER_ENTRY *current_line;
X
X numlines = 0;
X numentries = 0;
X current_line = NULL;
X
X while (fgets (buffer, STRINGSIZE, stdin))
X {
X if (!*buffer || isspace (*buffer))
X {
X continue;
X }
X new_element = Parse (buffer);
X
X ptr = new_element -> passwd.pw_passwd;
X if (!ptr[0])
X {
X Log ("Warning! %s (%s in %s) has a null password!\n",
X new_element -> passwd.pw_name,
X new_element -> passwd.pw_shell,
X new_element -> filename);
X continue;
X }
X if (ptr[0] == '*' || ptr[0] == '!')
X {
X Log ("User %s (in %s) has a locked password.\n",
X new_element -> passwd.pw_name,
X new_element -> filename);
X continue;
X }
X#ifdef CRACK_PW_VERIFY
X if (strlen (ptr) < 13)
X {
X Log ("User %s (in %s) has a short crypted password - ignoring.\n",
X new_element -> passwd.pw_name,
X new_element -> filename);
X continue;
X }
X if (strlen (ptr) > 13)
X {
X Log ("User %s (in %s) has a LONG crypted password - truncating.\n",
X new_element -> passwd.pw_name,
X new_element -> filename);
X ptr[13] = '\0';
X }
X#endif /* CRACK_PW_VERIFY */
X numentries++;
X
X if (ptr[0] == salt[0] && ptr[1] == salt[1])
X {
X new_element -> across = current_line;
X current_line = new_element;
X } else
X {
X if (current_line)
X {
X current_line -> next = user_root;
X }
X user_root = current_line;
X current_line = new_element;
X numlines++;
X salt[0] = ptr[0];
X salt[1] = ptr[1];
X }
X }
X
X if (current_line) /* last one tends to hang about */
X {
X current_line -> next = user_root;
X user_root = current_line;
X numlines++;
X }
X Log ("Loaded %d password entries into %d salted lines.\n",
X numentries, --numlines);
X
X return;
X}
X
Xvoid
XPrintGuess (eptr, guess)
X register struct USER_ENTRY *eptr;
X char *guess;
X{
X Log ("Guessed %s (%s in %s) [%s] \n",
X eptr -> passwd.pw_name,
X eptr -> passwd.pw_shell,
X eptr -> filename,
X#ifdef CRACK_PRINTOUT
X guess
X#else
X "<not printed>"
X#endif /* CRACK_PRINTOUT */
X );
X}
X/*
X * PASSWORD CRACKING LOW LEVEL FUNCTIONS
X */
X
Xint
XTryManyUsers (eptr, guess) /* returns 0 if all done this line */
X register struct USER_ENTRY *eptr;
X char *guess;
X{
X register int retval;
X char guess_crypted[STRINGSIZE];
X
X if (eptr -> done && !eptr -> across)


X {
X return (0);
X }

X strcpy (guess_crypted, crypt (guess, eptr -> passwd.pw_passwd));
X
X retval = 0;
X
X while (eptr)
X {
X#ifdef CRACK_VERBOSE /* Really want to fill your filestore ? */
X if (verbose_bool)
X {
X Log ("Trying '%s' on %s from line %s\n",
X guess,
X eptr -> passwd.pw_name,
X eptr -> filename);
X }
X#endif
X if (!strcmp (guess_crypted, eptr -> passwd.pw_passwd))
X {
X if (!eptr -> done) /* haven't printed it before */
X {
X PrintGuess (eptr, guess);
X }
X eptr -> done = 1;
X }
X retval += (!eptr -> done);
X eptr = eptr -> across;
X }
X
X return (retval);
X}
X
Xint
XTryOneUser (eptr, guess) /* returns non-null on guessed user */
X register struct USER_ENTRY *eptr;
X register char *guess;
X{
X if (!guess || !*guess || eptr -> done)


X {
X return (0);
X }

X#ifdef CRACK_VERBOSE
X if (verbose_bool)
X {
X Log ("Trying '%s' on %s from %s\n",
X guess,
X eptr -> passwd.pw_name,
X eptr -> filename);
X }
X#endif
X if (strcmp (crypt (guess, eptr -> passwd.pw_passwd),
X eptr -> passwd.pw_passwd))


X {
X return (0);
X }

X eptr -> done = 1;
X PrintGuess (eptr, guess);
X return (1);
X}
X/*
X * TOP LEVEL CRACKING FUNCTION INTERFACE ROUTINE - SINGLE USER ONLY
X */
X
Xint
XWordTry (entry_ptr, guess)
X register struct USER_ENTRY *entry_ptr;
X register char *guess;
X{
X int all_lower;
X int all_upper;
X register char *ptr;
X char guess2[STRINGSIZE];
X
X if (!guess[1]) /* avoid wasting time on initials */


X {
X return (0);
X }

X if (TryOneUser (entry_ptr, guess) ||
X TryOneUser (entry_ptr, Reverse (guess)))
X {
X return (1);
X }
X all_upper = all_lower = 1;
X ptr = guess;
X
X for (ptr = guess; *ptr; ptr++)
X {
X if (islower (*ptr))
X {
X all_upper = 0;
X } else if (isupper (*ptr))
X {
X all_lower = 0;
X }
X }
X
X if (!all_lower)
X {
X strcpy (guess2, Lowercase (guess));
X if (TryOneUser (entry_ptr, guess2) ||
X TryOneUser (entry_ptr, Reverse (guess2)))
X {
X return (1);
X }
X }
X if (!all_upper)
X {
X strcpy (guess2, Uppercase (guess));
X if (TryOneUser (entry_ptr, guess2) ||
X TryOneUser (entry_ptr, Reverse (guess2)))
X {
X return (1);


X }
X }
X return (0);
X}

X/*
X * END OF PASSWORD GUESSING LAYERS
X */
X
Xvoid
XPass1 ()
X{
X int cracked;
X struct USER_ENTRY *head;
X register char *ptr;
X register char *ptr2;
X char junk[STRINGSIZE];
X register struct USER_ENTRY *this;
X
X Log ("starting pass1 password information\n");
X
X for (head = user_root; head; head = head -> next)
X {
X for (this = head; this; this = this -> across)
X {
X /* username */
X ptr = this -> passwd.pw_name;
X if (WordTry (this, ptr))
X {
X continue;
X }
X /* usernameusername */
X strcpy (junk, ptr);
X strcat (junk, ptr);
X if (WordTry (this, junk))
X {
X continue;
X }
X /* usernameemanresu */
X strcpy (junk, ptr);
X strcat (junk, Reverse (ptr));
X if (WordTry (this, junk))
X {
X continue;
X }
X#ifdef CRACK_GECOS
X /* Gecos information field */
X cracked = 0;
X ptr = junk;
X strcpy (junk, this -> passwd.pw_gecos);
X if (*ptr == '-') /* never seen this, but... */
X {
X ptr++;
X }
X if (ptr2 = (char *) strchr (ptr, ';')) /* trim off junk */
X {
X *ptr2 = '\0';
X }
X if (ptr2 = (char *) strchr (ptr, ',')) /* trim off more junk */
X {
X *ptr2 = '\0';
X }
X for (;;)
X {
X if (ptr2 = (char *) strchr (ptr, ' '))
X {
X *(ptr2++) = '\0';
X }
X if (WordTry (this, ptr))
X {
X cracked++;
X break;
X }
X if (ptr2)
X {
X ptr = ptr2;
X while (*ptr && isspace (*ptr))
X {
X ptr++;
X }
X } else
X {
X break;
X }
X }
X
X if (cracked)
X {
X continue;
X }


X#endif /* CRACK_GECOS */
X }
X }

X return;
X}
X
Xvoid
XPass2 (dictfile)
X char *dictfile;
X{
X FILE *fp;
X register struct USER_ENTRY *head;
X int dictcount;
X struct DICT_ENTRY *dictroot;
X register struct DICT_ENTRY *scratch;
X int pointuser;
X char buffer[STRINGSIZE];
X
X Log ("Starting pass2 on dictionary %s\n", dictfile);
X
X if (!(fp = fopen (dictfile, "r")))
X {
X perror (dictfile);
X return;
X }
X dictcount = 0;
X dictroot = (struct DICT_ENTRY *) 0;
X
X while (fgets (buffer, STRINGSIZE, fp))
X {
X Trim (buffer);
X if (!*buffer)
X {
X continue;
X }
X scratch = (struct DICT_ENTRY *) malloc (sizeof (struct DICT_ENTRY));
X scratch -> word = Clone (buffer);
X scratch -> next = dictroot;
X dictroot = scratch;
X dictcount++;
X }
X
X fclose (fp);
X
X Log ("Loaded %d words from %s\n", dictcount, dictfile);
X
X if (dictcount <= 0)
X {
X Log ("Oops! Where did I get an empty dictionary from ?\n");
X return;
X }
X head = (struct USER_ENTRY *) 0; /* See "for" loop below */
X
X if (recover_bool) /* We are recovering */
X {
X recover_bool = 0; /* Switch it off */
X head = user_root; /* Start of the userlist */
X while (head && rusercount--) /* For the recover count */
X {
X head = head -> next;/* Skip to the next user */
X } /* God this is taking a long time to do */
X if (!head) /* Legs on the ground, feet at the bottom */
X {
X Log ("Recover: data changed : looking for %s ran off end of list",
X rusername);
X Log ("Exiting...\n");
X exit (0);
X }
X if (verify_recover && strcmp (rusername, head -> passwd.pw_name))
X {
X Log ("Recover: data changed : looking for %s found %s\n",
X rusername, head -> passwd.pw_name);
X Log ("Exiting...\n");


X exit (0);
X }
X }

X pointuser = 0; /* we havent pointed anyone yet */
X
X for (head = head ? head : user_root; head; head = head -> next)
X {
X SetPoint (dictfile, pointuser++, head -> passwd.pw_name);
X for (scratch = dictroot; scratch; scratch = scratch -> next)


X {
X if (!TryManyUsers (head, scratch->word))
X {

X break;
X }
X }
X }
X
X Log ("Freeing memory from pass of %s\n", dictfile);
X while (dictroot)
X {
X free (dictroot -> word);
X scratch = dictroot -> next;
X free (dictroot);
X dictroot = scratch;
X }
X}
X
Xint
Xmain (argc, argv)
X int argc;
X char *argv[];
X{
X int i;
X FILE *fp;
X char *file;
X int uerr;
X extern int optind;
X extern char *optarg;
X
X uerr = 0;
X pid = getpid (); /* fill this out FIRST THING */
X
X#ifdef CRACK_NETWORK
X if (gethostname (hostname, STRINGSIZE)) /* and this too ! */
X {
X perror ("gethostname");
X }
X#endif
X
X if (argc == 1)
X {
X uerr++;
X }
X while ((i = getopt (argc, argv, "vi:r:R:n:")) != EOF)
X {
X switch (i)
X {
X case 'v':
X verbose_bool = 1;
X break;
X case 'n':
X nice (atoi (optarg));
X break;
X case 'i':
X if (!freopen (optarg, "r", stdin))
X {
X perror (optarg);
X exit (1);
X }
X break;
X case 'R':
X verify_recover = 1;
X /* nobreak; */
X case 'r':
X if (GetPoint (optarg)) /* We are not a recovering machine */
X {
X exit (0); /* so, silently die... */
X }
X recover_bool = 1;
X break;
X default:
X case '?':
X uerr++;
X break;
X }
X }
X
X if (optind >= argc)
X {
X uerr++;
X }
X if (uerr)
X {
X fprintf (stderr,
X "Usage: %s [-v] [-i file] [-nn] [-<R|r> file] dictfile [...]\n",
X argv[0]);
X exit (1);
X }
X#ifdef CRACK_NETWORK
X sprintf (opfile, "out.%s.%d", hostname, pid);
X sprintf (diefile, "die.%s.%d", hostname, pid);
X sprintf (pointfile, "point.%s.%d", hostname, pid);
X#else
X sprintf (opfile, "out.%d", pid);
X sprintf (diefile, "die.%d", pid);
X sprintf (pointfile, "point.%d", pid);


X#endif /* CRACK_NETWORK */
X

X if (!freopen (opfile, "w", stdout))
X {
X perror ("freopen(stdout)");
X exit (1);
X }
X if (!freopen (opfile, "a", stderr))
X {
X perror ("freopen(stderr)");
X exit (1);
X }
X if (!(fp = fopen (diefile, "w")))
X {
X perror (diefile);
X exit (1);
X }
X Log ("Crack: A Sensible Password Cracker v%s by ADE Muffett, 1991\n",
X version);
X
X#ifdef CRACK_NETWORK
X Log ("We are running on networked machine %s\n", hostname);
X#endif
X
X if (recover_bool)
X {
X#ifdef CRACK_NETWORK
X Log ("We are recovering from a crash on %s, PID %d.\n", rhostname, rpid);
X#else
X Log ("We are recovering PID %d from a crash.\n", rpid);
X#endif
X Log ("From Dictionary %s, User number %d.\n", rdict, rusercount);
X Log ("Username must match %s\n", rusername);
X }
X fprintf (fp, "#!/bin/sh\n");
X#ifdef CRACK_NETWORK
X fprintf (fp, "rsh %s kill -15 %d\n", hostname, pid);
X#else
X fprintf (fp, "kill -15 %d\n", pid);
X#endif /* CRACK_NETWORK */
X fprintf (fp, "rm $0\n");
X fclose (fp);
X
X chmod (diefile, 0700);
X
X#ifdef FCRYPT


X init_des ();
X#endif
X

X /* Quick verify that we are sane ! */
X
X if (strcmp (crypt ("fredfred", "fredfred"), "frxWbx4IRuBBA"))
X {
X Log ("Version of crypt() being used internally is not compatible with standard.\n");
X Log ("Versions of 'gcc' have been known to cause compatibility problems.\n");
X Log ("If there is another reason for this, edit the source to remove this assertion.\n");
X Log ("Terminating...\n");
X exit (0);
X }
X signal (SIGTERM, CatchTERM);
X
X Log ("Loading...\n");
X
X LoadData ();
X
X if (!recover_bool)
X {
X /* We are starting afresh ! Ah, the birds in May ! */
X Pass1 ();
X } else
X {
X /* Some spodulous creep pulled our plug... */
X while ((optind < argc) && strcmp (argv[optind], rdict))
X {
X optind++; /* Fly over dicts that we have done */
X }
X }
X
X for (i = optind; i < argc; i++)
X {
X Pass2 (argv[i]);
X }
X
X Log ("Finished.\n");


X return (0);
X}
END_OF_FILE

if test 17109 -ne `wc -c <'Sources/crack-pwc.c'`; then
echo shar: \"'Sources/crack-pwc.c'\" unpacked with wrong size!
fi
# end of 'Sources/crack-pwc.c'
fi
if test -f 'Sources/goodpass.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/goodpass.c'\"
else
echo shar: Extracting \"'Sources/goodpass.c'\" \(8361 characters\)
sed "s/^X//" >'Sources/goodpass.c' <<'END_OF_FILE'
X#include <ctype.h>
X#include <pwd.h>
X#include <stdio.h>
X#include <string.h>
X#include <sys/file.h>
X
X/*
X * goodpass.c : A simple yes/no password sensibility function to be wired
X * into "passwd" & "yppasswd", etc. (c) ADE Muffett, 1991 (a...@aber.ac.uk).
X * This module is freely redistributable for use in software so long as this
X * copyright notice remains intact. Distributed as part of the 'Crack' suite
X * of password testing programs.
X */
X
X/* Usage:- */
X/* char *result = GoodPass(char *password); */
X/* where password is a text string to be tested for suitability */
X/* GoodPass returns NULL if the password is OK */
X/* GoodPass returns a diagnostic string if the password is NOT ok */
X
X#define PWLENGTH 8 /* significant length of text */
X#define MINDIFF 5 /* minimum number of different characters */
X#define MAXSTEP 3 /* max number of steps up/down in char set */
X#define MINLENGTH 6 /* minimum length of a password */
X#define STRINGSIZE 255 /* a standard buffer size */
X#define STRIDE 4 /* word skipping length */
X#undef DEBUG
X
Xstatic char *dikshunarys[] =
X{
X "/usr/dict/words",
X "/usr/local/lib/bad_pws.dat",
X NULL
X};
X
Xstatic int
XPmatch (control, string)
X char *control;
X char *string;
X{
X while (*control)
X {
X if (!*string)


X {
X return (0);
X }

X switch (*control)
X {
X case 'u':
X if (!isupper (*string))


X {
X return (0);
X }

X break;
X case 'l':
X if (!islower (*string))


X {
X return (0);
X }

X break;
X case 'd':
X if (!isdigit (*string))


X {
X return (0);
X }

X break;
X case 'c':
X if (!isalpha (*string))


X {
X return (0);
X }

X break;
X case '.':
X default:
X if (!isalnum (*string))


X {
X return (0);
X }

X break;
X }
X control++;
X string++;
X }
X return (1);
X}
X
Xstatic void


XTrim (string) /* remove trailing whitespace from a string */
X register char *string;
X{
X register char *ptr;
X
X for (ptr = string; *ptr; ptr++);
X while ((--ptr >= string) && isspace (*ptr));
X *(++ptr) = '\0';
X}
X

Xstatic char *


XReverse (str) /* return a pointer to a reversal */
X register char *str;
X{
X register int i;
X register int j;
X register char *ptr;
X static char area[STRINGSIZE];
X
X j = i = strlen (str);
X while (*str)
X {
X area[--i] = *str++;
X }
X area[j] = '\0';
X return (area);
X}

X/******* THE TEST FUNCTION *******/
X
Xstatic int
XTry (input, guess)
X register char *input;
X register char *guess;
X{
X if (!strncasecmp (input, guess, PWLENGTH) ||
X !strncasecmp (input, Reverse (guess), PWLENGTH))


X {
X return (-1);
X }

X return (0);
X}
X/******* DICTIONARY SEARCHING *******/
X
Xstatic int
XGetWord (fp, buff)
X FILE *fp;
X char *buff;
X{
X register int c;
X
X for (;;)
X {
X c = getc (fp);
X if (c == EOF)


X {
X return (-1);
X }

X if (c == '\n')
X {
X break;
X }
X *(buff++) = (char) c;
X }
X *buff = 0;


X return (0);
X}
X

Xstatic int
XDictSearch (input)
X char *input;
X{
X int i;
X int loops;
X register long top;
X register long bot;
X register long mid;
X long scratch;
X char word[STRINGSIZE];
X FILE *fp;
X char **dictionary;
X
X for (dictionary = dikshunarys; *dictionary; dictionary++)
X {
X if (!(fp = fopen (*dictionary, "r")))
X {
X perror (*dictionary);
X continue;
X }
X bot = 0L; /* start of file */
X fseek (fp, 0L, 2); /* to end of file */
X top = ftell (fp);
X
X for (loops = 0; loops < 1000; loops++)
X {
X mid = (top + bot) / 2; /* calculate the middle */
X scratch = mid;
X
X stride_loop:
X
X scratch -= STRIDE; /* calculate a bit beforehand */
X if (scratch < 0) /* error fixing */
X {
X mid = scratch = 0L;
X fseek (fp, 0L, 0);
X } else
X { /* find the start of the current word */
X fseek (fp, scratch, 0); /* go read the scratch buffer */
X fread (word, 1, STRIDE, fp);
X
X for (i = STRIDE - 1; i >= 0; i--)
X {
X if (word[i] == '\n') /* where 'mid' is is start of
X * word */
X {
X break;
X } else
X { /* mid is between words */
X mid--;
X }
X }
X if (i < 0)
X {
X goto stride_loop;
X }
X }
X
X fseek (fp, mid, 0);
X GetWord (fp, word);
X
X i = strncasecmp (input, word, PWLENGTH);
X
X if (i > 0)
X {
X bot = mid + strlen (word) + 1; /* why retest this word ever */
X } else if (i < 0)
X {
X if (mid >= top)
X {
X break;
X }
X top = mid;
X } else
X {
X fclose (fp);
X return (-1); /* found it */
X }
X }
X fclose (fp);


X }
X
X return (0);
X}

X/******* THE EXTERNAL CALL *******/
X
Xchar *
XGoodPass (input)
X char *input;


X{
X register int i;

X register char *ptr;
X register char *ptr2;
X struct passwd *pwd;
X char junk[STRINGSIZE];
X char password[STRINGSIZE];
X
X /* back it up. */
X strcpy (password, input);
X Trim (password);
X
X /* who is it ? */
X pwd = getpwuid (getuid ());
X if (!pwd)
X {
X perror ("getpwuid");
X return ("Error - no password entry found to verify against.");
X }
X /* size */
X if (strlen (password) < MINLENGTH)
X {
X return ("it is too short - use more characters.");
X }
X /* username */
X if (Try (password, pwd -> pw_name))
X {
X return ("it is your username");
X }
X /* usernameusername */
X strcpy (junk, pwd -> pw_name);
X strcat (junk, pwd -> pw_name);
X if (Try (password, junk))
X {
X return ("it is your username, doubled");
X }
X /* Gecos information field */
X strcpy (junk, pwd -> pw_gecos);
X ptr = junk;
X if (*ptr == '-') /* never seen this, but... */
X {
X ptr++;
X }
X if (ptr2 = strchr (ptr, ';')) /* trim off junk */
X {
X *ptr2 = '\0';
X }
X if (ptr2 = strchr (ptr, ',')) /* trim off more junk */
X {
X *ptr2 = '\0';
X }
X for (;;)
X {
X if (ptr2 = strchr (ptr, ' '))
X {
X *(ptr2++) = '\0';
X }
X if (Try (password, ptr))
X {
X return ("it is part of your name. Use something less obvious.");
X }
X if (ptr2)
X {
X ptr = ptr2;
X while (*ptr && isspace (*ptr))
X {
X ptr++;
X }
X } else
X {
X break;
X }
X }
X
X /* check for repeated characters */
X bzero (junk, sizeof (junk));
X for (i = 0; i < PWLENGTH && password[i]; i++)
X {
X if (!strchr (junk, password[i]))
X {
X strncat (junk, password + i, 1);
X }
X }
X if (strlen (junk) < MINDIFF)
X {
X return ("it does not contain enough different characters.\nUse more different characters.");
X }
X /* check for over simplicity */
X i = 0;
X ptr = password;
X while (ptr[0] && ptr[1])
X {
X if ((ptr[1] == (ptr[0] + 1)) ||
X (ptr[0] == (ptr[1] + 1)))
X {
X i++;
X }
X ptr++;
X }
X if (i > MAXSTEP)
X {
X return ("it is too simplistic. Try something more random.");
X }
X /* lets get a little silly... */
X if (Pmatch ("cdddccc", password))
X {
X return ("it looks like a new style car registration.");
X }
X if (Pmatch ("cccdddc", password))
X {
X return ("it looks like a old style car registration.");
X }
X if (Pmatch ("cccddd", password) || Pmatch ("dddccc", password))
X {
X return ("it looks like an old-style car registration.");
X }
X if (Pmatch ("ccddddddc", password))
X {
X return ("it looks like a National Insurance number.");
X }
X strcpy (junk, input);
X
X /* do a dictionary search here */
X if (DictSearch (junk))
X {
X return ("it is a guessable dictionary word.");
X }
X if (DictSearch (Reverse (junk)))
X {
X return ("it is a guessable reversed dictionary word.");
X }
X /* strip off possible initial number and do a dictionary search here */
X if (isdigit (junk[0]))
X {
X if (DictSearch (junk + 1))
X {
X return ("it is a digit + guessable dictionary word.");
X }
X if (DictSearch (Reverse (junk + 1)))
X {
X return ("it is a digit + guessable reversed dictionary word.");
X }
X }
X i = strlen (junk) - 1;
X if (isdigit (junk[i]))
X {
X junk[i] = '\0';
X if (DictSearch (junk))
X {
X return ("it is a guessable dictionary word + digit.");
X }
X if (DictSearch (Reverse (junk)))
X {
X return ("it is a guessable reversed dictionary word + digit.");
X }
X } else if (junk[i] == 's')
X {
X junk[i] = '\0';
X if (DictSearch (junk))
X {
X return ("it is a pluralised dictionary word.");
X }
X }
X return ((char *) NULL);
X}
X#ifdef DEBUG
Xmain (argc, argv)
X int argc;
X char *argv[];
X{
X int i;
X char *p;
X
X for (i = 1; i < argc; i++)
X {
X printf ("'%s'\n", argv[i]);
X
X if (p = GoodPass (argv[i]))
X {
X printf ("\t%s\n", p);
X } else
X {
X printf ("\tok\n");
X }
X }
X}
X#endif
END_OF_FILE
if test 8361 -ne `wc -c <'Sources/goodpass.c'`; then
echo shar: \"'Sources/goodpass.c'\" unpacked with wrong size!
fi
# end of 'Sources/goodpass.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone

Alec David Muffett

unread,
Aug 23, 1991, 11:04:38 AM8/23/91
to
Submitted-by: Alec David Muffett <a...@aber.ac.uk>
Posting-number: Volume 22, Issue 51
Archive-name: crack/part03
Environment: UNIX

#! /bin/sh


# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:

# "End of archive 3 (of 4)."
# Contents: Docs/README.ms Sources/crack-fcrypt.c
# Wrapped by aem@aberda on Fri Aug 23 13:20:42 1991


PATH=/bin:/usr/bin:/usr/ucb ; export PATH

if test -f 'Docs/README.ms' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Docs/README.ms'\"
else
echo shar: Extracting \"'Docs/README.ms'\" \(20032 characters\)
sed "s/^X//" >'Docs/README.ms' <<'END_OF_FILE'
X.de C
X.ie n .B "\\$1" \\$2
X.el .CW "\\$1" \\$2
X..
X.TL
X"Crack Version 3.2"
X.br
XA Sensible Password Checker for
X.UX
X.AU
XAlec D.E. Muffett
X.AI
XComputer Unit, University College of Wales
XAberystwyth, Wales, SY23 3DB
X.I a...@aber.ac.uk
X+44 970 622492
X.AB
X.B Crack \**
X.FS
X.C Crack
Xis available for anonymous FTP from
X.I "wuarchive.wustl.edu"
X(128.252.135.4) in
X.I ~/packages
X.FE
Xis a freely available program designed to find standard
X.UX
Xeight-character DES encrypted passwords by standard guessing techniques
Xoutlined below. It is written to be flexible, configurable and fast,
Xand to be able to make use of several networked hosts via the Berkeley
X.C rsh
Xprogram (or similar), where possible.
X.AE
X.NH 1
XIntent of this program
X.LP


XMy intentions, whilst writing this program, were

X.IP 1)
XTo provide the average system manager with a simple, flexible and fast
Xtool to find passwords which would be easily compromised by a dictionary
Xsearch.
X.IP 2)
XTo weaken the complacency which has developed amongst many (in)?experienced
X.UX
Xsystems managers about password security. Just because the
X.C crypt()
Xfunction cannot be reversed does not mean that your passwords are
Xsecure. If this program helps to raise the overall quotient of paranoia
Xjust one little bit, then it will have served its purpose and is all to
Xthe good.
X.LP
XI am quite certain that some childish morons out there will abuse the
Xwork that I have put into creating this program. It's up to them how
Xthey use it, but if it's used for some illegal purpose it's not my
Xintention, nor my fault. I hope they get caught.
X.LP


XCrack was not designed to do anything

X.I nasty ,
Xother than to attack passwords in sensible order. This is why I feel I


Xcan post it to the net without fear of recrimination.

XThis version of Crack is supplied with a (hopefully) portable version of
X.C fcrypt() ,
Xfor speed reasons. Fcrypt() is not yet widely available, but several
Xversions have now been posted to USENET, and with the growing ability to
Xaccess anonymous FTP databases like
X.B Archie ,
XI believe that people who really want access to such programs as
Xfcrypt() will be able to get them easily. People who need them but
Xdon't have the time to look, on the other hand, will not get them. This
Xis not a good thing if you are a systems manager, because it gives the
Xcrackers an advantage. My philosophy is:
X.I "give it to everyone, then at least the people who need it can get it" .
X.NH 1
XFcrypt() Statistics
X.LP
XThe version of fcrypt() that comes with Crack is some 3.4 times faster
Xthan the version that was originally supplied to me, and should
Xoutperform most others which are publicly available. I haven't tried
Xmany speed-demon style tricks, but rather I have gone for portability,
Xelegance and simplicity, where applicable
X.C 8-).
XOn a DECStation 5000/200, fcrypt() iterates ~550 times per second, and
Xoverall, I measure this to be 13 times faster than standard crypt().
XThere are faster versions available, but at least I feel free to
Xredistrubute this version without stepping on anyones toes.
X.LP
XA final note about my motives: If you think that I am a moron for
Xwriting and then distributing this program, and you think that the
Xprogram is in itself dangerous, I suggest that you carefully consider
Xthe fact that any moron could have written this program. Flames to
X.C /dev/null ,
Xplease.
X.NH 1
XImplementation
X.LP
XI have tried to make Crack as portable as possible without compromising
Xspeed. Needless to say, it is imperfect in the this respect, but I have
Xtried. If you have problems getting Crack up, please let me know what
Xthese problems were, and what system you were trying to put Crack up on.
XI believe that Crack will work on
X.B Xenix
Xand various versions of
X.B "System V" ,
Xbut it may require a little effort if your
X.UX
Xis not fairly modern.
X.LP
XThere have been some nasty stories sent back to me about problems
Xencountered due to the Crack script being written in c-shell. Because
Xof this, I enclose a program
X.C Crack.sh
Xwhich is a functionally equivalent script in Bourne shell, using
X.C nohup
Xto kick the cracker off into the background. If your version of c-shell
Xis non standard (ie: not BSDish) or you are worried, you may use
X.C Crack.sh
Xin
X.C Crack 's
Xplace. Note, though, that if you want to use the network options, you
Xwill also have to edit
X.C Scripts/RCrack
Xto change the program-name that is called on remote machines to
X.C Crack.sh .


XFor more on this, see below.

X.LP
XTo use the
X.C "Crack -network"
Xoption, you must have
X.C rsh ,
Xor a similar program.
X.C rsh
Xis a BSD-ism which has become fairly common on non-BSD systems. If you
Xdon't have it or something similar, let me know what you do have which
Xmight, with a little ingenuity, do the job, and I shall see what I can
Xdo. Again, have a look in
X.C Scripts/RCrack
Xif you want to play around.
X.QP
X.B Note:
X.B Xenix
Xusers and some others have a
X.C rcmd
Xprogram instead of
X.C rsh .
XI'm not sure of the correct syntax for this program, but it should not
Xbe hard to get it to work. There is a note about it in
X.C Scripts/RCrack
X.QP
XOn such System V based systems, users may also be missing the BSD
Xfunction
X.C gethostname() .
XIf this is so, but you
X.B do
Xhave the
X.C uname()
Xsystem call, define the macro
X.C CRACK_UNAME
Xin
X.C Sources/conf.h
Xinstead. This ought to fix the problem, but it
X.I may
Xneed a little user intervention first (it depends where your header file for
X.C uname()
Xis).
X.I "Caveat Emptor!"
X.NH 1
XMethod of Password Cracking
X.LP
XCrack does not take the serial approach to password guessing that other
Xprograms like the
X.B COPS
Xpassword cracker does. Rather, Crack makes two passes over the users'
Xpassword entries.
X.LP


XThe first pass bases its guesses on the contents of the

X.I gecos
Xfield (containing the users' real name), and the username itself. The
Xfirst pass is fast and usually very fruitful, and completes quite
Xquickly. You would be surprised at the number of spods out there who
Xstill think that their middle name, backwards and capitalised, is a good
Xpassword.
X.LP
XThe second pass is made by encrypting several pre-processed dictionaries
Xon the fly, and comparing the results with users passwords. Crack
Xoptimises the number of calls to the encryption function by sorting the
Xuser passwords by their
X.I "encryption salt"
Xbefore loading, so that the dictionaries only have to be encrypted once
Xfor each different salt. This generally saves about 30% of the calls
Xyou would have to make to
X.C crypt() .
X.LP
XThe preprocessed dictionaries are created my merging the source
Xdictionaries found in the directory
X.C DictSrc
Xand then truncating, sorting and uniq'ing the output from the
Xpreprocessor. The default dictionaries named are
X.C /usr/dict/words


Xwhich provides the bulk of the input data, and

X.C DictSrc/bad_pws.dat
Xwhich is meant to provide all of those non-dictionary passwords, such as
X.I 12345678
Xor
X.I qwerty .\**
X.FS
XExtra dictionaries (those used in Dan Klein's paper, below) can be
Xobtained via anonymous FTP from
X.I uunet.uu.net
X(192.48.96.2) as
X.I ~/pub/dictionaries.tar.Z
X.FE
X.LP
XIf you wish to add a dictionary of your own, just copy it into the
X.C DictSrc
Xdirectory and then delete the contents of the
X.C Dicts
Xdirectory. Your new dictionary will be merged in on the next run. Do
Xnot worry about replication of data, as the preprocessor driver script
Xsorts and uniq's the data before putting it into the
X.C Dicts
Xdirectory.
X.LP


XThe formats of the output dictionaries are:

X.IP a)
XUnique words that have been forced lowercase, forwards. These are the
Xmost common passwords you will find, thus they are tried first.
X.IP b)
XDictionary words which have been artificially pluralised, because not
Xmany dictionaries contain plurals.
X.IP c)
XDictionary words which were supplied in mixed-case (eg:
X.I Capitalised ).
X.IP d)
XDictionary words forced lowercase and backwards.
X.IP e)
XDictionary words, forced lowercase, with a leading or trailing 0 or 1
X(this may be extended by hacking Sources/crack-pp.c).
X.IP f)
XDictionary words, forced uppercase, forwards.
X.IP g)
XDictionary words, forced uppercase, backwards.
X.IP h)
XDictionary words which were supplied in mixed-case, backwards (eg:
X.I desilatipaC ).
X.sp 1v
X.LP
XThis choice of attack is entirely empirical, my own, and made up on the
Xspot. It has also been horrendously successful, and because Crack uses
Xeach of these dictionaries in turn, it tends to get passwords faster
Xthan a program like the
X.B COPS
Xpassword cracker which tries words every-which-way for each user.\**
X.FS
XFor more information, see "Foiling the Cracker: A Survey of, and
XImprovements to, Password Security" by Daniel Klein, available from
Xmajor FTP sites.
X.FE
X.QP
XOptimisation Note: Crack has an
X.B compile-time
Xoption, called
X.C CRACK_SHORT_PASSWDS ,
Xwhich, if
X.B not
Xdefined, makes the dictionary preprocessor
X.I "throw away"
Xwords which are less than 5 characters long. The reasoning for this is
Xthat many sites, with a semi-sensible
X.C passwd
Xprogram, will not have passwords shorter than 5 characters long.
X.QP
XIt is up to you whether you bother testing these short passwords, but I
Xwould recommend that you do so at least once, to be safe. (Setting the
Xoption also leads to having smaller pre-processed dictionaries. The
Xoption, however, is defined by default)
X.NH 1
XInstallation
X.LP
XCrack is one of those most unusual of beasties, a self-installing
Xprogram. Once the necessary configuration options have been set, the
Xexecutables are created via 'make' by running the main shellscript.
X.LP
XSome people have complained about this apparent weirdness, but it has
Xgrown up with Crack ever since the earliest network version, when I
Xcould not be bothered to log into several different machines with
Xseveral different architectures, just in order to build the binaries.
X.LP
XCrack needs to know where it has been installed. Please edit the
X.C CRACK_HOME
Xvariable in the Crack shellscript to the correct value. This variable
Xshould be set to an absolute path name (relative to
X.I ~user
Xis OK) through which the directory containing Crack may be accessed on
X.B all
Xthe machines that Crack will be run on.
X.LP
XThe other bit of installation you will have to do is decide whether
Xyou will want to use the
X.C \&-network
Xoption. If you do, edit the file
X.C Sources/conf.h
Xand define the
X.C CRACK_NETWORK
Xsymbol. This forces Crack to create all of its output files with an
Xembedded hostname (obtained by the
X.C gethostname()
Xroutine) so that you can keep track of output from all over the network.
XIf you have no
X.C gethostname()
Xbut have a
X.C uname()
Xsystem call, you can use that instead, by defining
X.C CRACK_UNAME
Xin
X.C Sources/conf.h .
X.LP


XYou will then have to generate a

X.C Scripts/network.conf
Xfile. This contains a list of hostnames to
X.C rsh
Xto, what their binary type is (useful when running a network Crack on
Xseveral different architectures), a guesstimate of their relative power
X(take your slowest machine as unary, and measure all others relative to
Xit), and a list of per-host default flags. There is an example of such
Xa file provided in the Scripts directory - take a look at it.
X.LP


XI also recommend that you play around with the

X.C #define s
Xin the file
X.C Sources/conf.h .
XEach switch has a small note explaining its meaning. Where I've been in
Xdoubt about the portability of certain library functions, usually I've
Xre-written it, so it shouldn't be much of a problem. Let me know of
Xyour problems.
X.C 8-).
X.NH 1
XCrack Usage
X.LP
X.DS B
X.fi
X.C Crack
X[\c
X.I options ]
X[\c
X.I bindir ]
X.C /etc/passwd
X[...other passwd files]
X.sp 1v
X.C "Crack -network"
X[\c
X.I options ]
X.C /etc/passwd
X[...other passwd files]
X.DE
X.LP
XWhere
X.B bindir
Xis the optional name of the directory where you want the binaries
Xinstalled. This is useful where you want to be able to run versions of
XCrack on several different architectures. If
X.B bindir
Xdoes not exist, a warning will be issued, and the directory, created.
X.QP
XNote:
X.B bindir
Xdefaults to the name
X.C generic
Xif not supplied.
X.QP
X.B "Yellow Pages (NIS) Users:"
XI have had some queries about how to get Crack running from a YP
Xpassword file. There are several methods, but by far the simplest is to
Xgenerate a passwd format file by running:-
X.DS B
X.C "ypcat passwd > passwd.yp"
X.DE
Xand then running Crack on this file.
X.NH 1
XOptions
X.IP "\fB-network\fP"
XThrows Crack into network mode, in which it reads the
X.C Scripts/network.conf
Xfile, splits its input into chunks which are sized according to the
Xpower of the target machine, and calls
X.C rsh
Xto run Crack on that machine. Options for Crack running on the target
Xmachine may be supplied on the command line (eg: verbose or recover
Xmode), or in the network.conf file if they pertain to specific hosts
X(eg:
X.C nice()
Xvalues).
X.IP "\fB-v\fP"
XSets verbose mode, whereby Crack will print every guess it is trying on
Xa per-user basis. This is a very quick way of flooding your filestore.
XIf you undefine the
X.C CRACK_VERBOSE
Xsymbol in
X.C Sources/conf.h ,
Xverbose mode will be permanently disabled.
X.IP "\fB-nvalue\fP"
XSets the process to be
X.C nice() ed
Xto
X.I value ,
Xso that the switch
X.C \&-n19
Xsets the Crack process to run at the lowest priority.
X.IP "\fB-rpointfile\fP"
XThis is only for use when running in
X.I recover
Xmode. When a running Crack starts pass 2, it periodically saves its
Xstate in a file named
X.C "point.<pid>"
Xor
X.C "point.<hostname>.<pid>"
Xdepending on your naming convention (see "Installation", above). This
Xfile can be used to recover where you were should a host crash. Simply
Xinvoke Crack in
X.B exactly
Xthe same manner as the last time, with the addition of the
X.C -rpoint.file.name
Xswitch. Crack will startup and read the file, and jump to slightly
Xbefore where it left off. If you are cracking a very large password
Xfile, this can save oodles of time after a crash.
X.QP
XIf you are running a
X.I network
XCrack, then the jobs will again be spawned onto all the machines of the
Xoriginal Crack. The program will then check that the host it is running
Xon is the same as is mentioned in the pointfile. If it is not, it will
Xsilently die. Thus, assuming that you supply the same input data and do
Xnot change your
X.C network.conf
Xfile, Crack should pick up
X.B exactly
Xwhere it left off. This is a bit inelegant, but it's better than
Xnothing at the moment.
X.NH
XMultiprocessing and parallelism
X.LP
XThe method of error recovery outlined above causes headaches for users
Xwho want to do multiprocessing on parallel architectures. Crack is in
Xno way parallel, and because of the way it's structured, readind stdin
Xfrom shellscript frontends, it is a pain to divide the work amongst
Xseveral processes via
X.C fork() ing.
X.LP
XThe hack solution to get several copies of Crack running on one machine
Xwith
X.I n
Xprocessors at the moment is to run with the
X.C CRACK_NETWORK
Xoption enabled, and insert
X.I n
Xcopies of the entry for your parallel machine into the
X.C Scripts/network.conf
Xfile. If you use the
X.C \&-r
Xoption in these circumstances however, you will get
X.I n
Xcopies of the recovered process running, only one of them will have the
Xcorrect input data. I'm working on this. My current solution is to
Xsave the current username in the checkpoint file, and test it on
Xstartup, but doing this
X.I may
Xbreak your recovery if you supply different input data (so that the data
Xis sorted even slightly differently). Hohum. If you want to use this
X.I "verify username"
Xfacility, use
X.C \&-R
Xin place of
X.C \&-r .
X.LP


XAs for not using the

X.C network.conf
Xfile to provide multiprocessing, I'm working on it.
X.NH 1
XNotes on fast crypt() implementations
X.LP


XThe stdlib version of the

X.C crypt()
Xsubroutine is incredibly slow. It is a
X.I massive
Xbottleneck to the execution of Crack and on typical platforms that you
Xget at universities, it is rare to find a machine which will achieve
Xmore than 50 standard
X.C crypt() s
Xper second. On low-end diskless workstations, you may expect 2 or 3 per
Xsecond. It was this slowness of the
X.C crypt()
Xalgorithm which originally supplied much of the security
X.UX
Xneeded.\**
X.FS
XSee: "Password Security, A Case History" by Bob Morris & Ken Thomson, in
Xthe
X.UX
XProgrammer Docs.
X.FE
X.LP
XHowever, there are now
X.C many
Ximplementations of faster versions of
X.C crypt()
Xto be found on the network. The one supplied with Crack v3.2 and
Xupwards is called
X.C fcrypt() .
X.LP
X.C fcrypt()
Xwas originally written in May 1986 by Robert Baldwin at MIT, and is a
Xgood version of the
X.C crypt()
Xsubroutine. I received a copy from Icarus Sparry at Bath University,
Xwho had made a couple of portability enhancements to the code.
X.LP
XI rewrote most of the tables and the KeySchedule generating algorithm in
Xthe original
X.I fdes-init.c
Xto knock 40% off the execution overhead of
X.C fcrypt()
Xin the form that it was shipped to me. I inlined a bunch of stuff, put
Xit into a single file, got some advice from Matt Bishop and Bob Baldwin
X[both of whom I am greatly indebted to] about what to do to the
X.C xform()
Xroutine and to the fcrypt function itself, and tidied up some algorithms.
XI've also added more lookup tables and reduced several formula for
Xfaster use.
X.C fcrypt()
Xis now barely recognisable as being based on its former incarnation.
X.LP
XOn a DecStation 5000/200, it is also ~13 times faster than the standard
Xcrypt (your mileage may vary with other architectures and compilers).
XThis speed puts
X.C fcrypt()
Xinto the "moderately fast" league of crypt implementations. By using
X.C fcrypt()
Xwith Crack, I extracted 135 passwords from my standard 1087 user
Xpassword file in a little over 1 hour using 3 networked machines. This
Xis from a moderately good password file.
X.LP
XWhy am I saying this sort of thing ? Am I scaremongering ? In a word, yes.
X.LP


XIf a fast version of

X.C crypt()
Xis wired into a program like Crack it can break a poorly passworded site
Xopen in minutes. There are such programs available, eg: the "Killer
XCracker" written by the anonymous "Doctor Dissector", with anonymous
Xmotives. It comes with a modified version of Baldwin's fcrypt, as a
XMS-DOS executable with a GNU copyleft licence.
X.LP
XThe point that needs to be hammered home is that unless something is
Xdone, and done soon, about the general quality of passwords on
X.UX
Xsystems, then in the near future our doors will be wide open to people
Xwho have programs like Crack and questionable motives.
X.NH 1
XSolutions and Conclusions
X.LP


XWhat can be done about this form of attack ?

X.LP


XYou must get a drop-in replacement for the

X.C passwd
Xand
X.C yppasswd
Xcommands; one which will stop people from choosing bad passwords in the
Xfirst place. There are several programs to do this; Matt Bishop's
X.C "passwd+"
Xand Clyde Hoover's
X.C "npasswd"
Xprogram are good examples which are freely available. Consult an
X.B Archie
Xdatabase for more details on where you can get them from.
X.LP
XA little common-sense is all that is required to vet passwords: I
Xenclose a module in the Sources directory
X.I goodpass.c
Xwhich I use in a modified version of the
X.C yppasswd
Xin order to provide some security. It is quite heavily customised for
Xuse in the UK, but it should be easily portable. The routine is invoked:
X.sp 1v
X.DS B
X.C "char *retval = GoodPass(char *input);"
X.DE
X.LP
Xwhere
X.C input
Xis the password under test, and
X.C retval
Xwill be set either to NULL (if the password is OK) or to a diagnostic
Xstring which says what is wrong with the password. It is far less
Xcomplex than a system such as
X.I passwd+ ,
Xbut still effective enough to make a password file withstand
X.C Crack .


XIt would be nice if an organisation (such as

X.B CERT ?)
Xcould be persuaded to supply skeletons of
X.I sensible
Xpasswd commands for the public good, as well as an archive of security
Xrelated utilities\**
Xon top of the excellent
X.C COPS .
X.FS
X.C COPS
Xis available for anonymous FTP from
X.I "cert.sei.cmu.edu"
X(128.237.253.5) in
X.I ~/cops
X.FE
XHowever, for
X.UX
Xsecurity to improve on a global scale, we will also require pressure on
Xthe vendors, so that programs are written correctly from the beginning.
END_OF_FILE
if test 20032 -ne `wc -c <'Docs/README.ms'`; then
echo shar: \"'Docs/README.ms'\" unpacked with wrong size!
fi
# end of 'Docs/README.ms'
fi
if test -f 'Sources/crack-fcrypt.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack-fcrypt.c'\"
else
echo shar: Extracting \"'Sources/crack-fcrypt.c'\" \(24641 characters\)
sed "s/^X//" >'Sources/crack-fcrypt.c' <<'END_OF_FILE'


X/*
X * This program is copyright (c) Alec Muffett 1991 except for certain

X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
X * Sparry and Alec Muffett. The author(s) disclaims all responsibility or
X * liability with respect to it's usage or its effect upon hardware or
X * computer systems. This software is in the public domain and is freely
X * redistributable PROVIDED that this notice remains intact.
X */
X

X/*
X * Misc defs for the fast password transform optimisations.
X */
X
X#include "crack.h" /* contains switches - AEM */
X
X/*
X * Rename the types for greater convenience ? - This is from original code.
X */
X#define reg register
X#define uns unsigned
X#define unsb uns char
X#define unsl uns long
X
X/*
X * Types for the different ways to represent DES bit patterns. Bits are
X * always right justified within fields. Bits which have lower indices in
X * the NBS spec are stored in the vax bits with less significance (e.g., Bit
X * 1 of NBS spec is stored in the bit with weight 2 ** 0 to the Vax.
X */
X
X#define obpb1 unsb /* One bit per byte. */
X#define sbpb6 unsb /* Six bits per byte, 6 held. */
X#define sbpb6R unsb /* Six bits per byte Reversed order, 6 held. */
X#define sbpb24 unsl /* Six bits per byte, 24 held. */
X#define ebpb24 unsl /* Eight bits per bit, 24 held. */
X#define fbpb4 unsb /* Four bits per byte, 4 held. */
X#define fbpb4R unsb /* Four bits per byte Reversed order, 4 held. */
X
X/*
X * The operation (6 * x) is often better optimised as this (for really
X * braindead compilers) - AEM
X */
X
X#ifdef BRAINDEAD6
X#define SIX_TIMES(exprn) (((exprn) << 2) + ((exprn) << 1))
X#else
X#define SIX_TIMES(exprn) (6 * (exprn))
X#endif /* BRAINDEAD6 */
X
X/*
X * Data segment gathered into one place - AEM
X */
X
X/* Try to keep this stuff long aligned - AEM */
Xstatic char iobuf[16];
Xstatic obpb1 L[32], R[32];
Xstatic obpb1 crypt_block[72]; /* 72 is next multiple of 8 bytes after 66 */
Xstatic sbpb24 KS[32];
Xstatic sbpb24 S0H[64], S1H[64], S2H[64], S3H[64];
Xstatic sbpb24 S4H[64], S5H[64], S6H[64], S7H[64];
Xstatic sbpb24 S0L[64], S1L[64], S2L[64], S3L[64];
Xstatic sbpb24 S4L[64], S5L[64], S6L[64], S7L[64];
Xstatic sbpb24 out96[4];
X
X/*
X * These used to be rather slow and frequently used functions - AEM
X */
X
X#define TF_TO_SIXBIT(tf) \
X (sbpb24)((tf & 077L) | \
X ((tf & 07700L) << 2) | \
X ((tf & 0770000L) << 4) | \
X ((tf & 077000000L) << 6))
X
X#define SIXBIT_TO_TF(sb) \
X (ebpb24)((sb & 0x3fL) | \
X ((sb & 0x3f00L) >> 2) | \
X ((sb & 0x3f0000L) >> 4) | \
X ((sb & 0x3f000000L) >> 6))
X/*
X * Start of the real thing
X */
X
Xvoid
XtoBA64 (quarters /* , crypt_block */ )
X reg sbpb24 *quarters;
X{
X static unsb UnDoE[] =
X {
X 1, 2, 3, 4, 7, 8, 9, 10,
X 13, 14, 15, 16, 19, 20, 21, 22,
X 25, 26, 27, 28, 31, 32, 33, 34,
X 37, 38, 39, 40, 43, 44, 45, 46
X };
X static unsb FP[] =
X {
X 39, 7, 47, 15, 55, 23, 63, 31,
X 38, 6, 46, 14, 54, 22, 62, 30,
X 37, 5, 45, 13, 53, 21, 61, 29,
X 36, 4, 44, 12, 52, 20, 60, 28,
X 35, 3, 43, 11, 51, 19, 59, 27,
X 34, 2, 42, 10, 50, 18, 58, 26,
X 33, 1, 41, 9, 49, 17, 57, 25,
X 32, 0, 40, 8, 48, 16, 56, 24,
X };
X
X reg i;
X static obpb1 tmpE[48];
X reg unsb *onebits48;
X reg sbpb24 quarter;
X
X onebits48 = tmpE;
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X /*
X * Testing one bit and setting another may be faster than shifting and
X * setting - it's certainly not slower - AEM
X */
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X /* the next loop used to be the call: undoe (tmpE, L); - AEM */
X
X for (i = 0; i < 32; i++)
X {
X L[i] = tmpE[UnDoE[i]];
X }
X
X onebits48 = tmpE;
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X /* the next loop used to be the call: undoe (tmpE, R); - AEM */
X
X for (i = 0; i < 32; i++)
X {
X R[i] = tmpE[UnDoE[i]];
X }
X
X /* the next loop used to be the call: Fperm (crypt_block); - AEM */
X
X for (i = 0; i < 64; i++)
X {
X crypt_block[i] = L[FP[i]];
X }
X}
X
Xvoid
Xfsetkey ()
X{
X /*
X * This used to be utterly horrendous. It still is, but it's much, much,
X * smaller... AEM.
X */
X static unsb KeyToKS[] =
X {
X 9, 50, 33, 59, 48, 16, 32, 56, 1, 8, 18, 41, 2, 34, 25, 24,
X 43, 57, 58, 0, 35, 26, 17, 40, 21, 27, 38, 53, 36, 3, 46, 29,
X 4, 52, 22, 28, 60, 20, 37, 62, 14, 19, 44, 13, 12, 61, 54, 30,
X 1, 42, 25, 51, 40, 8, 24, 48, 58, 0, 10, 33, 59, 26, 17, 16,
X 35, 49, 50, 57, 56, 18, 9, 32, 13, 19, 30, 45, 28, 62, 38, 21,
X 27, 44, 14, 20, 52, 12, 29, 54, 6, 11, 36, 5, 4, 53, 46, 22,
X 50, 26, 9, 35, 24, 57, 8, 32, 42, 49, 59, 17, 43, 10, 1, 0,
X 48, 33, 34, 41, 40, 2, 58, 16, 60, 3, 14, 29, 12, 46, 22, 5,
X 11, 28, 61, 4, 36, 27, 13, 38, 53, 62, 20, 52, 19, 37, 30, 6,
X 34, 10, 58, 48, 8, 41, 57, 16, 26, 33, 43, 1, 56, 59, 50, 49,
X 32, 17, 18, 25, 24, 51, 42, 0, 44, 54, 61, 13, 27, 30, 6, 52,
X 62, 12, 45, 19, 20, 11, 60, 22, 37, 46, 4, 36, 3, 21, 14, 53,
X 18, 59, 42, 32, 57, 25, 41, 0, 10, 17, 56, 50, 40, 43, 34, 33,
X 16, 1, 2, 9, 8, 35, 26, 49, 28, 38, 45, 60, 11, 14, 53, 36,
X 46, 27, 29, 3, 4, 62, 44, 6, 21, 30, 19, 20, 54, 5, 61, 37,
X 2, 43, 26, 16, 41, 9, 25, 49, 59, 1, 40, 34, 24, 56, 18, 17,
X 0, 50, 51, 58, 57, 48, 10, 33, 12, 22, 29, 44, 62, 61, 37, 20,
X 30, 11, 13, 54, 19, 46, 28, 53, 5, 14, 3, 4, 38, 52, 45, 21,
X 51, 56, 10, 0, 25, 58, 9, 33, 43, 50, 24, 18, 8, 40, 2, 1,
X 49, 34, 35, 42, 41, 32, 59, 17, 27, 6, 13, 28, 46, 45, 21, 4,
X 14, 62, 60, 38, 3, 30, 12, 37, 52, 61, 54, 19, 22, 36, 29, 5,
X 35, 40, 59, 49, 9, 42, 58, 17, 56, 34, 8, 2, 57, 24, 51, 50,
X 33, 18, 48, 26, 25, 16, 43, 1, 11, 53, 60, 12, 30, 29, 5, 19,
X 61, 46, 44, 22, 54, 14, 27, 21, 36, 45, 38, 3, 6, 20, 13, 52,
X 56, 32, 51, 41, 1, 34, 50, 9, 48, 26, 0, 59, 49, 16, 43, 42,
X 25, 10, 40, 18, 17, 8, 35, 58, 3, 45, 52, 4, 22, 21, 60, 11,
X 53, 38, 36, 14, 46, 6, 19, 13, 28, 37, 30, 62, 61, 12, 5, 44,
X 40, 16, 35, 25, 50, 18, 34, 58, 32, 10, 49, 43, 33, 0, 56, 26,
X 9, 59, 24, 2, 1, 57, 48, 42, 54, 29, 36, 19, 6, 5, 44, 62,
X 37, 22, 20, 61, 30, 53, 3, 60, 12, 21, 14, 46, 45, 27, 52, 28,
X 24, 0, 48, 9, 34, 2, 18, 42, 16, 59, 33, 56, 17, 49, 40, 10,
X 58, 43, 8, 51, 50, 41, 32, 26, 38, 13, 20, 3, 53, 52, 28, 46,
X 21, 6, 4, 45, 14, 37, 54, 44, 27, 5, 61, 30, 29, 11, 36, 12,
X 8, 49, 32, 58, 18, 51, 2, 26, 0, 43, 17, 40, 1, 33, 24, 59,
X 42, 56, 57, 35, 34, 25, 16, 10, 22, 60, 4, 54, 37, 36, 12, 30,
X 5, 53, 19, 29, 61, 21, 38, 28, 11, 52, 45, 14, 13, 62, 20, 27,
X 57, 33, 16, 42, 2, 35, 51, 10, 49, 56, 1, 24, 50, 17, 8, 43,
X 26, 40, 41, 48, 18, 9, 0, 59, 6, 44, 19, 38, 21, 20, 27, 14,
X 52, 37, 3, 13, 45, 5, 22, 12, 62, 36, 29, 61, 60, 46, 4, 11,
X 41, 17, 0, 26, 51, 48, 35, 59, 33, 40, 50, 8, 34, 1, 57, 56,
X 10, 24, 25, 32, 2, 58, 49, 43, 53, 28, 3, 22, 5, 4, 11, 61,
X 36, 21, 54, 60, 29, 52, 6, 27, 46, 20, 13, 45, 44, 30, 19, 62,
X 25, 1, 49, 10, 35, 32, 48, 43, 17, 24, 34, 57, 18, 50, 41, 40,
X 59, 8, 9, 16, 51, 42, 33, 56, 37, 12, 54, 6, 52, 19, 62, 45,
X 20, 5, 38, 44, 13, 36, 53, 11, 30, 4, 60, 29, 28, 14, 3, 46,
X 17, 58, 41, 2, 56, 24, 40, 35, 9, 16, 26, 49, 10, 42, 33, 32,
X 51, 0, 1, 8, 43, 34, 25, 48, 29, 4, 46, 61, 44, 11, 54, 37,
X 12, 60, 30, 36, 5, 28, 45, 3, 22, 27, 52, 21, 20, 6, 62, 38
X };
X
X reg int i, j, r;
X reg unsb *k;
X
X k = KeyToKS;
X
X for (i = 0; i < 32; i++) /* loops cache better ? - AEM */
X {
X r = 0;
X for (j = 0; j < 24; j++)
X {
X r |= crypt_block[*(k++)] << j;
X }
X KS[i] = TF_TO_SIXBIT (r);
X }
X}
X
Xvoid
Xxform (quarters, saltvalue)
X sbpb24 *quarters;
X sbpb24 saltvalue;
X{
X union
X {
X sbpb24 b[2];
X sbpb6 c[8];
X } sdata;
X
X#ifdef sun /* Icarus Sparry, Bath */
X#define STEP --
X#define START &sdata.c[7]
X#define Dl sdata.b[1]
X#define Dh sdata.b[0]
X#else
X#define STEP ++
X#define START &sdata.c[0]
X#define Dl sdata.b[0]
X#define Dh sdata.b[1]
X#endif
X sbpb24 Rl, Rh;
X sbpb24 Ll, Lh;
X
X reg int loop;
X reg sbpb24 k;
X reg sbpb6 *dp;
X reg sbpb24 *kp;
X reg sbpb24 *kend;
X
X Ll = Lh = Rl = Rh = 0;
X
X kend = &KS[32];
X
X /*
X * Thanks to Matt Bishop for this idea... AEM.
X */
X
X#ifndef FDES_4BYTE
X#define SIZEFIX 0
X#define INDIRECT(a,b) (a)[b]
X#else
X#define SIZEFIX 2 /* "n" where 2^n == sizeof(sbpb24) */
X#define INDIRECT(a,b) (*((sbpb24 *)(((unsigned char *) a) + (b))))
X#endif
X
X for (loop = 25; loop-- > 0; /* nothing */ )
X {
X for (kp = KS; kp < kend; /* nothing */ )
X {
X k = (Rl ^ Rh) & saltvalue;
X Dl = (k ^ Rl ^ *kp++) << SIZEFIX;
X Dh = (k ^ Rh ^ *kp++) << SIZEFIX;
X
X /*
X * Oddly enough, direct addressing of dp slows things down, as
X * well as knackering portability - AEM
X */
X dp = START;
X Lh ^= INDIRECT (S0H, *dp STEP);
X Lh ^= INDIRECT (S1H, *dp STEP);
X Lh ^= INDIRECT (S2H, *dp STEP);
X Lh ^= INDIRECT (S3H, *dp STEP);
X Lh ^= INDIRECT (S4H, *dp STEP);
X Lh ^= INDIRECT (S5H, *dp STEP);
X Lh ^= INDIRECT (S6H, *dp STEP);
X Lh ^= INDIRECT (S7H, *dp STEP);
X
X dp = START;
X Ll ^= INDIRECT (S0L, *dp STEP);
X Ll ^= INDIRECT (S1L, *dp STEP);
X Ll ^= INDIRECT (S2L, *dp STEP);
X Ll ^= INDIRECT (S3L, *dp STEP);
X Ll ^= INDIRECT (S4L, *dp STEP);
X Ll ^= INDIRECT (S5L, *dp STEP);
X Ll ^= INDIRECT (S6L, *dp STEP);
X Ll ^= INDIRECT (S7L, *dp STEP);
X
X k = (Ll ^ Lh) & saltvalue;
X Dl = (k ^ Ll ^ *kp++) << SIZEFIX;
X Dh = (k ^ Lh ^ *kp++) << SIZEFIX;
X
X dp = START;
X Rh ^= INDIRECT (S0H, *dp STEP);
X Rh ^= INDIRECT (S1H, *dp STEP);
X Rh ^= INDIRECT (S2H, *dp STEP);
X Rh ^= INDIRECT (S3H, *dp STEP);
X Rh ^= INDIRECT (S4H, *dp STEP);
X Rh ^= INDIRECT (S5H, *dp STEP);
X Rh ^= INDIRECT (S6H, *dp STEP);
X Rh ^= INDIRECT (S7H, *dp STEP);
X
X dp = START;
X Rl ^= INDIRECT (S0L, *dp STEP);
X Rl ^= INDIRECT (S1L, *dp STEP);
X Rl ^= INDIRECT (S2L, *dp STEP);
X Rl ^= INDIRECT (S3L, *dp STEP);
X Rl ^= INDIRECT (S4L, *dp STEP);
X Rl ^= INDIRECT (S5L, *dp STEP);
X Rl ^= INDIRECT (S6L, *dp STEP);
X Rl ^= INDIRECT (S7L, *dp STEP);
X }
X
X Ll ^= Rl;
X Lh ^= Rh;
X Rl ^= Ll;
X Rh ^= Lh;
X Ll ^= Rl;
X Lh ^= Rh;
X }
X
X {
X reg sbpb24 *qp;
X qp = quarters;
X *qp++ = Ll;
X *qp++ = Lh;
X *qp++ = Rl;
X *qp++ = Rh;


X }
X return;
X}
X

Xchar *
Xfcrypt (pw, salt)
X char *pw;
X char *salt;
X{
X /* Table lookups for salts reduce fcrypt() overhead dramatically */
X static sbpb24 salt0[] =
X {
X 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
X 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
X 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1,
X 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 5, 6, 7, 8, 9, 10,
X 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
X 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 32, 33, 34, 35, 36,
X 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
X 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4,
X 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
X 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
X 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
X 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4,
X 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
X 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
X 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
X 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4
X };
X static sbpb24 salt1[] =
X {
X 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600,
X 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112,
X 2176, 2240, 2304, 2368, 2432, 2496, 2560, 2624,
X 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136,
X 3200, 3264, 3328, 3392, 3456, 3520, 3584, 3648,
X 3712, 3776, 3840, 3904, 3968, 4032, 0, 64,
X 128, 192, 256, 320, 384, 448, 512, 576,
X 640, 704, 320, 384, 448, 512, 576, 640,
X 704, 768, 832, 896, 960, 1024, 1088, 1152,
X 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664,
X 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176,
X 2240, 2304, 2368, 2048, 2112, 2176, 2240, 2304,
X 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816,
X 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328,
X 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840,
X 3904, 3968, 4032, 0, 64, 128, 192, 256,
X 320, 384, 448, 512, 576, 640, 704, 768,
X 832, 896, 960, 1024, 1088, 1152, 1216, 1280,
X 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792,
X 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304,
X 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816,
X 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328,
X 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840,
X 3904, 3968, 4032, 0, 64, 128, 192, 256,
X 320, 384, 448, 512, 576, 640, 704, 768,
X 832, 896, 960, 1024, 1088, 1152, 1216, 1280,
X 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792,
X 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304,
X 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816,
X 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328,
X 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840,
X 3904, 3968, 4032, 0, 64, 128, 192, 256
X };
X
X /* final perutation desalting */
X static obpb1 final[] =
X {
X 46, 47, 48, 49, 50, 51, 52, 53,
X 54, 55, 56, 57, 65, 66, 67, 68,
X 69, 70, 71, 72, 73, 74, 75, 76,
X 77, 78, 79, 80, 81, 82, 83, 84,
X 85, 86, 87, 88, 89, 90, 97, 98,
X 99, 100, 101, 102, 103, 104, 105, 106,
X 107, 108, 109, 110, 111, 112, 113, 114,
X 115, 116, 117, 118, 119, 120, 121, 122,
X 123, 124, 125, 126, 127, 128, 129, 130,
X 131, 132, 133, 134, 135, 136, 137, 138,
X 139, 140, 141, 142, 143, 144, 145, 146,
X 147, 148, 149, 150, 151, 152, 153, 154,
X 155, 156, 157, 158, 159, 160, 161, 162,
X 163, 164, 165, 166, 167, 168, 169, 170,
X 171, 172, 173, 174, 175, 176, 177, 178,
X 179, 180, 181, 182, 183, 184, 185, 186,
X 187, 188, 189, 190, 191, 192, 193, 194,
X 195, 196, 197, 198, 199, 200, 201, 202,
X 203, 204, 205, 206, 207, 208, 209, 210,
X 211, 212, 213, 214, 215, 216, 217, 218,
X 219, 220, 221, 222, 223, 224, 225, 226,
X 227, 228, 229, 230, 231, 232, 233, 234,
X 235, 236, 237, 238, 239, 240, 241, 242,
X 243, 244, 245, 246, 247, 248, 249, 250,
X 251, 252, 253, 254, 255,
X /* Truncate overflow bits at 256 */
X 0, 1, 2, 3, 4, 5, 6, 7,
X 8, 9, 10, 11, 12, 13, 14, 15,
X 16, 17, 18, 19, 20, 21, 22, 23,
X 24, 25, 26, 27, 28, 29, 30, 31,
X 32, 33, 34, 35, 36, 37, 38, 39,
X 40, 41, 42, 43, 44, 45, 46, 47,
X 48, 49, 50, 51, 52, 53, 54, 55,
X 56, 57, 58
X };
X
X reg int i, j, k;
X reg long int *lip;
X sbpb24 saltvalue;
X
X#if defined(BUILTIN_CLEAR)
X lip = (long int *) crypt_block;
X for (i = (sizeof (crypt_block) / sizeof (long int)); i > 0; i--)
X {
X *(lip++) = 0L;
X }
X#elif defined(BZERO)
X bzero (crypt_block, 66);
X#else
X for (i = 0; i < 66; i++)
X {
X crypt_block[i] = '\0';
X }
X#endif
X
X for (i = 0; (k = *pw) && i < 64; pw++)
X {
X crypt_block[i++] = (k >> 6) & 01;
X crypt_block[i++] = (k >> 5) & 01;
X crypt_block[i++] = (k >> 4) & 01;
X crypt_block[i++] = (k >> 3) & 01;
X crypt_block[i++] = (k >> 2) & 01;
X crypt_block[i++] = (k >> 1) & 01;
X crypt_block[i++] = (k >> 0) & 01;
X i++; /* have to skip one here (parity bit) */
X }
X
X fsetkey ( /* crypt_block */ );
X
X
X#if defined(BUILTIN_CLEAR)
X lip = (long int *) crypt_block;
X for (i = (sizeof (crypt_block) / sizeof (long int)); i > 0; i--)
X {
X *(lip++) = 0L;
X }
X#elif defined(BZERO)
X bzero (crypt_block, 66);
X#else
X for (i = 0; i < 66; i++)
X {
X crypt_block[i] = '\0';
X }
X#endif
X
X iobuf[0] = salt[0];
X iobuf[1] = salt[1];
X
X saltvalue = salt0[iobuf[0]] | salt1[iobuf[1]];
X saltvalue = TF_TO_SIXBIT (saltvalue);
X
X xform (out96, saltvalue);
X
X toBA64 (out96 /* , crypt_block */ );
X
X for (i = 0; i < 11; i++)
X {
X k = 0;
X
X for (j = 0; j < 6; j++)
X {
X k = (k << 1) | crypt_block[SIX_TIMES (i) + j];
X }
X iobuf[i + 2] = final[k];
X }
X
X iobuf[i + 2] = 0;
X
X if (iobuf[1] == 0)
X {
X iobuf[1] = iobuf[0];
X }
X return (iobuf);
X}
X/********* INITIALISATION ROUTINES *********/
X
Xfbpb4
XlookupS (tableno, t6bits)
X unsl tableno;
X sbpb6R t6bits;
X{
X static fbpb4R S[8][64] =
X {
X 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
X 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
X 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
X 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
X
X 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
X 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
X 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
X 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
X
X 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
X 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
X 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
X 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
X
X 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
X 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
X 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
X 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
X
X 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
X 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
X 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
X 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
X
X 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
X 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
X 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
X 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
X
X 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
X 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
X 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
X 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
X
X 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
X 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
X 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
X 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
X };
X sbpb6 fixed6bits;
X fbpb4R r;
X fbpb4 fixedr;
X
X fixed6bits = (((t6bits >> 0) & 01) << 5) +
X (((t6bits >> 1) & 01) << 3) +
X (((t6bits >> 2) & 01) << 2) +
X (((t6bits >> 3) & 01) << 1) +
X (((t6bits >> 4) & 01) << 0) +
X (((t6bits >> 5) & 01) << 4);
X
X r = S[tableno][fixed6bits];
X
X fixedr = (((r >> 3) & 01) << 0) +
X (((r >> 2) & 01) << 1) +
X (((r >> 1) & 01) << 2) +
X (((r >> 0) & 01) << 3);
X
X return (fixedr);
X}
X
Xvoid
Xinit (tableno, lowptr, highptr)
X unsl tableno;
X sbpb24 *lowptr, *highptr;
X{
X
X static unsb P[] =
X {
X 15, 6, 19, 20,
X 28, 11, 27, 16,
X 0, 14, 22, 25,
X 4, 17, 30, 9,
X 1, 7, 23, 13,
X 31, 26, 2, 8,
X 18, 12, 29, 5,
X 21, 10, 3, 24,
X };
X
X static unsb E[] =
X {
X 31, 0, 1, 2, 3, 4,
X 3, 4, 5, 6, 7, 8,
X 7, 8, 9, 10, 11, 12,
X 11, 12, 13, 14, 15, 16,
X 15, 16, 17, 18, 19, 20,
X 19, 20, 21, 22, 23, 24,
X 23, 24, 25, 26, 27, 28,
X 27, 28, 29, 30, 31, 0,
X };
X
X static obpb1 tmp32[32];
X static obpb1 tmpP32[32];
X static obpb1 tmpE[32];
X
X int j, k, i;
X int tablenoX4;
X reg sbpb24 spare24;
X
X tablenoX4 = tableno * 4;
X
X for (j = 0; j < 64; j++)
X {
X k = lookupS (tableno, j);
X
X for (i = 0; i < 32; i++)
X {
X tmp32[i] = 0;
X }
X for (i = 0; i < 4; i++)
X {
X tmp32[tablenoX4 + i] = (k >> i) & 01;
X }
X for (i = 0; i < 32; i++)
X {
X tmpP32[i] = tmp32[P[i]];
X }
X for (i = 0; i < 48; i++)
X {
X tmpE[i] = tmpP32[E[i]];
X }
X
X lowptr[j] = 0;
X highptr[j] = 0;
X
X for (i = 0; i < 24; i++)
X {
X lowptr[j] |= tmpE[i] << i;
X }
X for (k = 0, i = 24; i < 48; i++, k++)
X {
X highptr[j] |= tmpE[i] << k;
X }
X
X spare24 = lowptr[j]; /* to allow for macro expansion */
X lowptr[j] = TF_TO_SIXBIT (spare24);
X spare24 = highptr[j]; /* to allow for macro expansion */
X highptr[j] = TF_TO_SIXBIT (spare24);
X }
X}
Xinit_des ()
X{
X init (0, S0L, S0H);
X init (1, S1L, S1H);
X init (2, S2L, S2H);
X init (3, S3L, S3H);
X init (4, S4L, S4H);
X init (5, S5L, S5H);
X init (6, S6L, S6H);
X init (7, S7L, S7H);
X}
END_OF_FILE
if test 24641 -ne `wc -c <'Sources/crack-fcrypt.c'`; then
echo shar: \"'Sources/crack-fcrypt.c'\" unpacked with wrong size!
fi
# end of 'Sources/crack-fcrypt.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone

Alec David Muffett

unread,
Aug 23, 1991, 11:04:58 AM8/23/91
to
Submitted-by: Alec David Muffett <a...@aber.ac.uk>
Posting-number: Volume 22, Issue 52
Archive-name: crack/part04
Environment: UNIX

#! /bin/sh


# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:

# "End of archive 4 (of 4)."
# Contents: Docs/README.ps
# Wrapped by aem@aberda on Fri Aug 23 13:20:43 1991


PATH=/bin:/usr/bin:/usr/ucb ; export PATH

if test -f 'Docs/README.ps' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Docs/README.ps'\"
else
echo shar: Extracting \"'Docs/README.ps'\" \(37992 characters\)
sed "s/^X//" >'Docs/README.ps' <<'END_OF_FILE'
X%!PS-Adobe-3.0
X%%Creator: groff version 1.02
X%%DocumentNeededResources: font Times-Bold
X%%+ font Times-Italic
X%%+ font Times-Roman
X%%+ font Courier
X%%DocumentSuppliedResources: procset grops 1.02 0
X%%Pages: 6
X%%PageOrder: Ascend
X%%Orientation: Portrait
X%%EndComments
X%%BeginProlog
X%%BeginResource: procset grops 1.02 0
X
X/setpacking where {
X pop
X currentpacking
X true setpacking
X} if
X
X/grops 120 dict dup begin
X
X% The ASCII code of the space character.
X/SC 32 def
X
X/A /show load def
X/B { 0 SC 3 -1 roll widthshow } bind def
X/C { 0 exch ashow } bind def
X/D { 0 exch 0 SC 5 2 roll awidthshow } bind def
X/E { 0 rmoveto show } bind def
X/F { 0 rmoveto 0 SC 3 -1 roll widthshow } bind def
X/G { 0 rmoveto 0 exch ashow } bind def
X/H { 0 rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
X/I { 0 exch rmoveto show } bind def
X/J { 0 exch rmoveto 0 SC 3 -1 roll widthshow } bind def
X/K { 0 exch rmoveto 0 exch ashow } bind def
X/L { 0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
X/M { rmoveto show } bind def
X/N { rmoveto 0 SC 3 -1 roll widthshow } bind def
X/O { rmoveto 0 exch ashow } bind def
X/P { rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
X/Q { moveto show } bind def
X/R { moveto 0 SC 3 -1 roll widthshow } bind def
X/S { moveto 0 exch ashow } bind def
X/T { moveto 0 exch 0 SC 5 2 roll awidthshow } bind def
X
X% name size font SF -
X
X/SF {
X findfont exch
X [ exch dup 0 exch 0 exch neg 0 0 ] makefont
X dup setfont
X [ exch /setfont cvx ] cvx bind def
X} bind def
X
X% name a c d font MF -
X
X/MF {
X findfont
X [ 5 2 roll
X 0 3 1 roll % b
X neg 0 0 ] makefont
X dup setfont
X [ exch /setfont cvx ] cvx bind def
X} bind def
X
X/level0 0 def
X/RES 0 def
X/PL 0 def
X/LS 0 def
X
X% BP -
X
X/BP {
X /level0 save def
X 1 setlinecap
X 1 setlinejoin
X 72 RES div dup scale
X LS {
X 90 rotate
X } {
X 0 PL translate
X } ifelse
X 1 -1 scale
X} bind def
X
X/EP {
X level0 restore
X showpage
X} bind def
X
X
X% centerx centery radius startangle endangle DA -
X
X/DA {
X newpath arcn stroke
X} bind def
X
X% x y SN - x' y'
X% round a position to nearest (pixel + (.25,.25))
X
X/SN {
X transform
X .25 sub exch .25 sub exch
X round .25 add exch round .25 add exch
X itransform
X} bind def
X
X% endx endy startx starty DL -
X% we round the endpoints of the line, so that parallel horizontal
X% and vertical lines will appear even
X
X/DL {
X SN
X moveto
X SN
X lineto stroke
X} bind def
X
X% centerx centery radius DC -
X
X/DC {
X newpath 0 360 arc closepath
X} bind def
X
X
X/TM matrix def
X
X% width height centerx centery DE -
X
X/DE {
X TM currentmatrix pop
X translate scale newpath 0 0 .5 0 360 arc closepath
X TM setmatrix
X} bind def
X
X% these are for splines
X
X/RC /rcurveto load def
X/RL /rlineto load def
X/ST /stroke load def
X/MT /moveto load def
X/CL /closepath load def
X
X% fill the last path
X
X% amount FL -
X
X/FL {
X currentgray exch setgray fill setgray
X} bind def
X
X% fill with the ``current color''
X
X/BL /fill load def
X
X/LW /setlinewidth load def
X% new_font_name encoding_vector old_font_name RE -
X
X/RE {
X findfont
X dup maxlength dict begin
X {
X 1 index /FID ne { def } { pop pop } ifelse
X } forall
X /Encoding exch def
X dup /FontName exch def
X currentdict end definefont pop
X} bind def
X
X/DEFS 0 def
X
X% hpos vpos EBEGIN -
X
X/EBEGIN {
X moveto
X DEFS begin
X} bind def
X
X/EEND /end load def
X
X/CNT 0 def
X/level1 0 def
X
X% llx lly newwid wid newht ht newllx newlly PBEGIN -
X
X/PBEGIN {
X /level1 save def
X translate
X div 3 1 roll div exch scale
X neg exch neg exch translate
X % set the graphics state to default values
X 0 setgray
X 0 setlinecap
X 1 setlinewidth
X 0 setlinejoin
X 10 setmiterlimit
X [] 0 setdash
X /setstrokeadjust where {
X pop
X false setstrokeadjust
X } if
X /setoverprint where {
X pop
X false setoverprint
X } if
X newpath
X /CNT countdictstack def
X /showpage {} def
X} bind def
X
X/PEND {
X clear
X countdictstack CNT sub { end } repeat
X level1 restore
X} bind def
X
Xend def
X
X/setpacking where {
X pop
X setpacking
X} if
X%%EndResource
X%%IncludeResource: font Times-Bold
X%%IncludeResource: font Times-Italic
X%%IncludeResource: font Times-Roman
X%%IncludeResource: font Courier
Xgrops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
X792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
X/Ydieresis/trademark/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
X/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
X/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/exclam
X/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright
X/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven
X/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J
X/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
X/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z
X/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
X/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl/endash
X/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut/dotaccent/breve
X/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash/quotedblbase/OE/Lslash
X/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis
X/copyright/ordfeminine/guilsinglleft/logicalnot/minus/registered/macron/degree
X/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla
X/onesuperior/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
X/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla
X/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth
X/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave
X/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex
X/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave
X/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde
X/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn
X/ydieresis]def/Courier@0 ENC0/Courier RE/Times-Roman@0 ENC0/Times-Roman RE
X/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
X%%EndProlog
X%%Page: 1 1
X%%BeginPageSetup
XBP
X%%EndPageSetup
X/F0 12/Times-Bold@0 SF("Crack V)235.398 123 Q(ersion 3.2")-1.104 E 3(AS)184.428
X138 S(ensible Password Checker for)202.764 138 Q/F1 9.6/Times-Bold@0 SF(UNIX)3
XE F0<ae>A/F2 10/Times-Italic@0 SF(Alec D.E. Muffett)253.005 162 Q/F3 10
X/Times-Roman@0 SF(Computer Unit, University College of W)198.685 180 Q(ales)-.8
XE(Aberystwyth, W)222.99 192 Q(ales, SY23 3DB)-.8 E F2(aem@aber)254.52 204 Q
X(.ac.uk)-1.11 E F3(+44 970 622492)255.18 216 Q F2(ABSTRACT)264.385 252 Q/F4 10
X/Times-Bold@0 SF(Crack)133 279.6 Q/F5 7/Times-Roman@0 SF(1)159.66 275.5 Q F3
X.018(is a freely available program designed to \214nd standard)165.678 279.6 R
X/F6 8/Times-Roman@0 SF(UNIX)2.518 E F3(eight-character)2.518 E .744
X(DES encrypted passwords by standard guessing techniques outlined below)108
X291.6 R 5.745(.I)-.65 G 3.245(ti)423.73 291.6 S 3.245(sw)432.535 291.6 S
X(ritten)446.89 291.6 Q 1.431(to be \215exible, con\214gurable and fast, and to\
X be able to make use of several networked)108 303.6 R(hosts via the Berkeley)
X108 315.6 Q/F7 10/Courier@0 SF(rsh)2.5 E F3
X(program \(or similar\), where possible.)2.5 E F4 2.5(1. Intent)72 351.6 R
X(of this pr)2.5 E(ogram)-.18 E F3
X(My intentions, whilst writing this program, were)72 367.2 Q 14.17(1\) T)72
X382.8 R 2.828(op)-.7 G .328(rovide the average system manager with a simple, \
X\215exible and fast tool to \214nd passwords which)115.238 382.8 R
X(would be easily compromised by a dictionary search.)97 394.8 Q 14.17(2\) T)72
X410.4 R 4.295(ow)-.7 G 1.794
X(eaken the complacency which has developed amongst many \(in\)?experienced)
X118.925 410.4 R F6(UNIX)4.294 E F3(systems)4.294 E .526
X(managers about password security)97 422.4 R 3.026(.J)-.65 G .526
X(ust because the)244.814 422.4 R F7(crypt\(\))3.026 E F3 .526
X(function cannot be reversed does not)3.026 F .582
X(mean that your passwords are secure.)97 434.4 R .582
X(If this program helps to raise the overall quotient of paranoia)5.582 F(just \
Xone little bit, then it will have served its purpose and is all to the good.)97
X446.4 Q 2.769(Ia)72 462 S 2.769(mq)82.539 462 S .269(uite certain that some ch\
Xildish morons out there will abuse the work that I have put into creating this)
X98.088 462 R 2.794(program. It')72 474 R 2.794(su)-.55 G 2.794(pt)134.248 474 S
X2.794(ot)144.822 474 S .294(hem how they use it, but if it')155.396 474 R 2.794
X(su)-.55 G .294(sed for some illegal purpose it')286.918 474 R 2.793(sn)-.55 G
X.293(ot my intention, nor)423.671 474 R(my fault. I hope they get caught.)72
X486 Q .252(Crack was not designed to do anything)72 501.6 R F2(nasty)2.752 E F3
X2.752(,o)C .252(ther than to attack passwords in sensible order)263.166 501.6 R
X5.253(.T)-.55 G .253(his is why)462.934 501.6 R 2.877(If)72 513.6 S .376
X(eel I can post it to the net without fear of recrimination.)81.537 513.6 R
X.376(This version of Crack is supplied with a \(hope-)5.376 F .697
X(fully\) portable version of)72 525.6 R F7(fcrypt\(\))3.197 E F3 3.197(,f)C
X.697(or speed reasons.)234.575 525.6 R .698
X(Fcrypt\(\) is not yet widely available, but several)5.697 F 2.148
X(versions have now been posted to USENET)72 537.6 R 4.648(,a)-.74 G 2.148
X(nd with the growing ability to access anonymous FTP)271.266 537.6 R 1.081
X(databases like)72 549.6 R F4(Ar)3.581 E(chie)-.18 E F3 3.581(,Ib)C 1.082(elie\
Xve that people who really want access to such programs as fcrypt\(\) will be)
X179.174 549.6 R .388(able to get them easily)72 561.6 R 5.388(.P)-.65 G .388
X(eople who need them but don')176.34 561.6 R 2.888(th)-.18 G .387
X(ave the time to look, on the other hand, will not)310.138 561.6 R .013
X(get them.)72 573.6 R .013
X(This is not a good thing if you are a systems manager)5.013 F 2.513(,b)-.4 G
X.013(ecause it gives the crackers an advantage.)337.592 573.6 R
X(My philosophy is:)72 585.6 Q F2
X(give it to everyone, then at least the people who need it can get it)2.5 E F3
X(.)A F4 2.5(2. Fcrypt\(\))72 609.6 R(Statistics)2.5 E F3 .469(The version of f\
Xcrypt\(\) that comes with Crack is some 3.4 times faster than the version that\
X was originally)72 625.2 R 1.593(supplied to me, and should outperform most ot\
Xhers which are publicly available.)72 637.2 R 4.094(Ih)6.594 G(aven')430.452
X637.2 Q 4.094(tt)-.18 G 1.594(ried many)462.136 637.2 R .738
X(speed-demon style tricks, but rather I have gone for portability)72 649.2 R
X3.238(,e)-.65 G .738(legance and simplicity)338.68 649.2 R 3.237(,w)-.65 G .737
X(here applicable)442.453 649.2 R F7(8-\).)72 661.2 Q F3 .131(On a DECStation 5\
X000/200, fcrypt\(\) iterates ~550 times per second, and overall, I measure thi\
Xs to be)5.131 F .967(13 times faster than standard crypt\(\).)72 673.2 R .967
X(There are faster versions available, but at least I feel free to redis-)5.967
XF(trubute this version without stepping on anyones toes.)72 685.2 Q .32 LW 144
X708.2 72 708.2 DL/F8 5.6/Times-Roman@0 SF(1)82 716.72 Q/F9 8/Courier@0 SF
X(Crack)2 3.28 M F6(is available for anonymous FTP from)2 E/F10 8/Times-Italic@0
XSF(wuar)2 E(chive.wustl.edu)-.296 E F6(\(128.252.135.4\) in)2 E F10(~/packages)
X2 E EP
X%%Page: 2 2
X%%BeginPageSetup
XBP
X%%EndPageSetup
X/F0 10/Times-Roman@0 SF(-2-)282.17 48 Q 3.378<418c>72 84 S .879(nal note about\
X my motives: If you think that I am a moron for writing and then distributing \
Xthis pro-)88.158 84 R .824(gram, and you think that the program is in itself d\
Xangerous, I suggest that you carefully consider the fact)72 96 R
X(that any moron could have written this program.)72 108 Q(Flames to)5 E/F1 10
X/Courier@0 SF(/dev/null)2.5 E F0 2.5(,p)C(lease.)375.98 108 Q/F2 10
X/Times-Bold@0 SF 2.5(3. Implementation)72 132 R F0 4.031(Ih)72 147.6 S 1.531
X(ave tried to make Crack as portable as possible without compromising speed.)
X84.361 147.6 R 1.531(Needless to say)6.531 F 4.032(,i)-.65 G 4.032(ti)490.518
X147.6 S(s)500.11 147.6 Q .592(imperfect in the this respect, but I have tried.)
X72 159.6 R .591(If you have problems getting Crack up, please let me know)5.592
XF .489
X(what these problems were, and what system you were trying to put Crack up on.)
X72 171.6 R 2.989(Ib)5.489 G .489(elieve that Crack will)416.713 171.6 R .187
X(work on)72 183.6 R F2(Xenix)2.687 E F0 .186(and various versions of)2.686 F F2
X.186(System V)2.686 F F0 2.686(,b)C .186(ut it may require a little ef)282.536
X183.6 R .186(fort if your)-.18 F/F3 8/Times-Roman@0 SF(UNIX)2.686 E F0 .186
X(is not fairly)2.686 F(modern.)72 195.6 Q .956(There have been some nasty stor\
Xies sent back to me about problems encountered due to the Crack script)72 211.2
XR .619(being written in c-shell.)72 223.2 R .619
X(Because of this, I enclose a program)5.619 F F1(Crack.sh)3.119 E F0 .618
X(which is a functionally equiva-)3.119 F .44
X(lent script in Bourne shell, using)72 235.2 R F1(nohup)2.94 E F0 .44
X(to kick the cracker of)2.94 F 2.94(fi)-.18 G .44(nto the background.)335.68
X235.2 R .44(If your version of c-)5.44 F 1.398
X(shell is non standard \(ie: not BSDish\) or you are worried, you may use)72
X247.2 R F1(Crack.sh)3.897 E F0(in)3.897 E F1(Crack)3.897 E F0 2.497 -.55('s p)D
X(lace.).55 E .059(Note, though, that if you want to use the network options, y\
Xou will also have to edit)72 259.2 R F1(Scripts/RCrack)2.56 E F0(to)2.56 E
X(change the program-name that is called on remote machines to)72 271.2 Q F1
X(Crack.sh)2.5 E F0 5(.F)C(or more on this, see below)386.34 271.2 Q(.)-.65 E
X2.835 -.7(To u)72 286.8 T 1.435(se the).7 F F1 1.434(Crack -network)3.934 F F0
X1.434(option, you must have)3.934 F F1(rsh)3.934 E F0 3.934(,o)C 3.934(ras)
X335.692 286.8 S 1.434(imilar program.)355.22 286.8 R F1(rsh)6.434 E F0 1.434
X(is a BSD-ism)3.934 F .611(which has become fairly common on non-BSD systems.)
X72 298.8 R .611(If you don')5.611 F 3.111(th)-.18 G .611
X(ave it or something similar)363.791 298.8 R 3.112(,l)-.4 G .612(et me)481.448
X298.8 R 1.306(know what you do have which might, with a little ingenuity)72
X310.8 R 3.805(,d)-.65 G 3.805(ot)334.87 310.8 S 1.305
X(he job, and I shall see what I can do.)346.455 310.8 R(Again, have a look in)
X72 322.8 Q F1(Scripts/RCrack)2.5 E F0(if you want to play around.)2.5 E F2 .314
X(Note: Xenix)97 338.4 R F0 .314(users and some others have a)2.814 F F1(rcmd)
X2.815 E F0 .315(program instead of)2.815 F F1(rsh)2.815 E F0 5.315(.I)C .315
X('m not sure of the)406.64 338.4 R 1.19
X(correct syntax for this program, but it should not be hard to get it to work.)
X97 350.4 R 1.189(There is a note)6.189 F(about it in)97 362.4 Q F1
X(Scripts/RCrack)2.5 E F0 1.1
X(On such System V based systems, users may also be missing the BSD function)97
X378 R F1(gethost-)3.6 E(name\(\))97 390 Q F0 8.102(.I)C 5.602(ft)146.932 390 S
X3.102(his is so, but you)158.644 390 R F2(do)5.601 E F0 3.101(have the)5.601 F
XF1(uname\(\))5.601 E F0 3.101(system call, de\214ne the macro)5.601 F F1
X(CRACK_UNAME)97 402 Q F0(in)2.504 E F1(Sources/conf.h)2.504 E F0 .005
X(instead. This ought to \214x the problem, but it)2.504 F/F4 10/Times-Italic@0
XSF(may)2.505 E F0(need)2.505 E 4.131(al)97 414 S 1.631
X(ittle user intervention \214rst \(it depends where your header \214le for)
X108.351 414 R F1(uname\(\))4.13 E F0(is\).)4.13 E F4(Caveat)6.63 E(Emptor!)97
X426 Q F2 2.5(4. Method)72 450 R(of Password Cracking)2.5 E F0 .268(Crack does \
Xnot take the serial approach to password guessing that other programs like the)
X72 465.6 R F2(COPS)2.769 E F0(password)2.769 E(cracker does.)72 477.6 Q(Rather)
X5 E 2.5(,C)-.4 G(rack makes two passes over the users' password entries.)167.68
X477.6 Q .372(The \214rst pass bases its guesses on the contents of the)72 493.2
XR F4(gecos)2.872 E F0 .372
X(\214eld \(containing the users' real name\), and the)2.872 F .282
X(username itself.)72 505.2 R .283(The \214rst pass is fast and usually very fr\
Xuitful, and completes quite quickly)5.283 F 5.283(.Y)-.65 G .283(ou would be)
X453.994 505.2 R 1.395(surprised at the number of spods out there who still thi\
Xnk that their middle name, backwards and capi-)72 517.2 R
X(talised, is a good password.)72 529.2 Q 1.219(The second pass is made by encr\
Xypting several pre-processed dictionaries on the \215y)72 544.8 R 3.72(,a)-.65
XG 1.22(nd comparing the)431.57 544.8 R .197(results with users passwords.)72
X556.8 R .197
X(Crack optimises the number of calls to the encryption function by sorting the)
X5.197 F .875(user passwords by their)72 568.8 R F4 .875(encryption salt)3.375 F
XF0 .876(before loading, so that the dictionaries only have to be encrypted)
X3.375 F 1.824(once for each dif)72 580.8 R 1.824(ferent salt.)-.18 F 1.823
X(This generally saves about 30% of the calls you would have to make to)6.824 F
XF1(crypt\(\))72 592.8 Q F0(.)A .083
X(The preprocessed dictionaries are created my mer)72 608.4 R .084
X(ging the source dictionaries found in the directory)-.18 F F1(Dict-)2.584 E
X(Src)72 620.4 Q F0 .944
X(and then truncating, sorting and uniq'ing the output from the preprocessor)
X3.445 F 5.944(.T)-.55 G .944(he default dictionaries)413.242 620.4 R 6.628
X(named are)72 632.4 R F1(/usr/dict/words)9.128 E F0 6.628
X(which provides the bulk of the input data, and)9.128 F F1(Dict-)9.129 E
X(Src/bad_pws.dat)72 644.4 Q F0 .498
X(which is meant to provide all of those non-dictionary passwords, such as)2.999
XF F4(12345678)2.998 E F0(or)72 656.4 Q F4(qwerty)2.5 E F0(.)A/F5 7
X/Times-Roman@0 SF(2)112.55 652.3 Q F0 .739
X(If you wish to add a dictionary of your own, just copy it into the)72 672 R F1
X(DictSrc)3.238 E F0 .738(directory and then delete the)3.238 F .926
X(contents of the)72 684 R F1(Dicts)3.426 E F0(directory)3.426 E 5.926(.Y)-.65 G
X.926(our new dictionary will be mer)219.68 684 R .926(ged in on the next run.)
X-.18 F .927(Do not worry)5.926 F .161
X(about replication of data, as the preprocessor driver script sorts and uniq')
X72 696 R 2.661(st)-.55 G .161(he data before putting it into the)374.714 696 R
X.32 LW 144 704 72 704 DL/F6 5.6/Times-Roman@0 SF(2)82 712.52 Q F3 1.319
X(Extra dictionaries \(those used in Dan Klein')2 3.28 N 3.319(sp)-.44 G(aper)
X245.569 715.8 Q 3.319(,b)-.32 G 1.32
X(elow\) can be obtained via anonymous FTP from)268.336 715.8 R/F7 8
X/Times-Italic@0 SF(uunet.uu.net)72 725.8 Q F3(\(192.48.96.2\) as)2 E F7
X(~/pub/dictionaries.tar)2 E(.Z)-.888 E EP
X%%Page: 3 3
X%%BeginPageSetup
XBP
X%%EndPageSetup
X/F0 10/Times-Roman@0 SF(-3-)282.17 48 Q/F1 10/Courier@0 SF(Dicts)72 84 Q F0
X(directory)2.5 E(.)-.65 E(The formats of the output dictionaries are:)72 99.6 Q
X14.73(a\) Unique)72 115.2 R 1.144
X(words that have been forced lowercase, forwards.)3.644 F 1.145
X(These are the most common passwords)6.145 F
X(you will \214nd, thus they are tried \214rst.)97 127.2 Q 14.17(b\) Dictionary)
X72 142.8 R .473(words which have been arti\214cially pluralised, because not m\
Xany dictionaries contain plu-)2.974 F(rals.)97 154.8 Q 14.73(c\) Dictionary)72
X170.4 R(words which were supplied in mixed-case \(eg:)2.5 E/F2 10
X/Times-Italic@0 SF(Capitalised)2.5 E F0(\).)A 14.17(d\) Dictionary)72 186 R
X(words forced lowercase and backwards.)2.5 E 14.73(e\) Dictionary)72 201.6 R
X.401(words, forced lowercase, with a leading or trailing 0 or 1 \(this may be \
Xextended by hack-)2.9 F(ing Sources/crack-pp.c\).)97 213.6 Q 15.84
X(f\) Dictionary)72 229.2 R(words, forced uppercase, forwards.)2.5 E 14.17
X(g\) Dictionary)72 244.8 R(words, forced uppercase, backwards.)2.5 E 14.17
X(h\) Dictionary)72 260.4 R
X(words which were supplied in mixed-case, backwards \(eg:)2.5 E F2(desilatipaC)
X2.5 E F0(\).)A .065
X(This choice of attack is entirely empirical, my own, and made up on the spot.)
X72 288 R .064(It has also been horrendously)5.064 F .209(successful, and becau\
Xse Crack uses each of these dictionaries in turn, it tends to get passwords fa\
Xster than a)72 300 R(program like the)72 312 Q/F3 10/Times-Bold@0 SF(COPS)2.5 E
XF0(password cracker which tries words every-which-way for each user)2.5 E(.)
X-.55 E/F4 7/Times-Roman@0 SF(3)441.62 307.9 Q F0 2.115
X(Optimisation Note: Crack has an)97 327.6 R F3(compile-time)4.615 E F0 2.115
X(option, called)4.615 F F1(CRACK_SHORT_PASSWDS)4.615 E F0(,)A .095(which, if)97
X339.6 R F3(not)2.595 E F0 .094(de\214ned, makes the dictionary preprocessor)
X2.595 F F2(thr)2.594 E .094(ow away)-.37 F F0 .094(words which are less than)
X2.594 F 2.644(5c)97 351.6 S .144(haracters long.)109.084 351.6 R .144
X(The reasoning for this is that many sites, with a semi-sensible)5.144 F F1
X(passwd)2.644 E F0(pro-)2.644 E
X(gram, will not have passwords shorter than 5 characters long.)97 363.6 Q .561
X(It is up to you whether you bother testing these short passwords, but I would\
X recommend that)97 379.2 R 1.983(you do so at least once, to be safe.)97 391.2
XR 1.983(\(Setting the option also leads to having smaller pre-)6.983 F
X(processed dictionaries.)97 403.2 Q(The option, however)5 E 2.5(,i)-.4 G 2.5
X(sd)283.51 403.2 S(e\214ned by default\))294.9 403.2 Q F3 2.5(5. Installation)
X72 427.2 R F0 .212
X(Crack is one of those most unusual of beasties, a self-installing program.)72
X442.8 R .212(Once the necessary con\214guration)5.212 F(options have been set,\
X the executables are created via 'make' by running the main shellscript.)72
X454.8 Q .122(Some people have complained about this apparent weirdness, but it\
X has grown up with Crack ever since the)72 470.4 R .714(earliest network versi\
Xon, when I could not be bothered to log into several dif)72 482.4 R .714
X(ferent machines with several)-.18 F(dif)72 494.4 Q
X(ferent architectures, just in order to build the binaries.)-.18 E 1.587
X(Crack needs to know where it has been installed.)72 510 R 1.588
X(Please edit the)6.588 F F1(CRACK_HOME)4.088 E F0 1.588(variable in the Crack)
X4.088 F .918(shellscript to the correct value.)72 522 R .917
X(This variable should be set to an absolute path name \(relative to)5.917 F F2
X(~user)3.417 E F0(is)3.417 E .334
X(OK\) through which the directory containing Crack may be accessed on)72 534 R
XF3(all)2.835 E F0 .335(the machines that Crack will be)2.835 F(run on.)72 546 Q
X1.133(The other bit of installation you will have to do is decide whether you \
Xwill want to use the)72 561.6 R F1(-network)3.633 E F0 .358
X(option. If you do, edit the \214le)72 573.6 R F1(Sources/conf.h)2.859 E F0
X.359(and de\214ne the)2.859 F F1(CRACK_NETWORK)2.859 E F0 2.859(symbol. This)
X2.859 F(forces)2.859 E .323(Crack to create all of its output \214les with an \
Xembedded hostname \(obtained by the)72 585.6 R F1(gethostname\(\))2.822 E F0
X(rou-)2.822 E .111
X(tine\) so that you can keep track of output from all over the network.)72
X597.6 R .112(If you have no)5.112 F F1(gethostname\(\))2.612 E F0(but)2.612 E
X6.528(have a)72 609.6 R F1(uname\(\))9.028 E F0 6.528
X(system call, you can use that instead, by de\214ning)9.028 F F1(CRACK_UNAME)
X9.027 E F0(in)9.027 E F1(Sources/conf.h)72 621.6 Q F0(.)A -1(Yo)72 637.2 S
X3.776(uw)1 G 1.276(ill then have to generate a)99.216 637.2 R F1
X(Scripts/network.conf)3.776 E F0 1.276
X(\214le. This contains a list of hostnames to)3.776 F F1(rsh)72 649.2 Q F0 .337
X(to, what their binary type is \(useful when running a network Crack on severa\
Xl dif)2.837 F .336(ferent architectures\),)-.18 F 2.563(ag)72 661.2 S .063
X(uesstimate of their relative power \(take your slowest machine as unary)84.003
X661.2 R 2.564(,a)-.65 G .064(nd measure all others relative to)375.65 661.2 R
X.214(it\), and a list of per)72 673.2 R .214(-host default \215ags.)-.2 F .214
X(There is an example of such a \214le provided in the Scripts directory -)5.214
XF(take a look at it.)72 685.2 Q .32 LW 144 698.2 72 698.2 DL/F5 5.6
X/Times-Roman@0 SF(3)82 706.72 Q/F6 8/Times-Roman@0 SF .151(For more informatio\
Xn, see "Foiling the Cracker: A Survey of, and Improvements to, Password Securi\
Xty" by)2 3.28 N(Daniel Klein, available from major FTP sites.)72 720 Q EP
X%%Page: 4 4
X%%BeginPageSetup
XBP
X%%EndPageSetup
X/F0 10/Times-Roman@0 SF(-4-)282.17 48 Q 3.106(Ia)72 84 S .606
X(lso recommend that you play around with the)82.876 84 R/F1 10/Courier@0 SF
X(#define)3.106 E F0 3.106(si)C 3.106(nt)323.37 84 S .606(he \214le)334.256 84 R
XF1(Sources/conf.h)3.106 E F0 5.606(.E)C .606(ach switch)460.904 84 R .661
X(has a small note explaining its meaning.)72 96 R .66
X(Where I've been in doubt about the portability of certain library)5.661 F .324
X(functions, usually I've re-written it, so it shouldn')72 108 R 2.824(tb)-.18 G
X2.824(em)283.842 108 S .325(uch of a problem.)298.886 108 R .325
X(Let me know of your problems.)5.325 F F1(8-\).)72 120 Q/F2 10/Times-Bold@0 SF
X2.5(6. Crack)72 144 R(Usage)2.5 E F1(Crack)148.285 165.6 Q F0([)2.5 E/F3 10
X/Times-Italic@0 SF(options)A F0 2.5(][)C F3(bindir)222.725 165.6 Q F0(])A F1
X(/etc/passwd)2.5 E F0([...other passwd \214les])2.5 E F1(Crack -network)148.285
X189.6 Q F0([)2.5 E F3(options)A F0(])A F1(/etc/passwd)2.5 E F0
X([...other passwd \214les])2.5 E(Where)72 211.2 Q F2(bindir)3.422 E F0 .921
X(is the optional name of the directory where you want the binaries installed.)
X3.422 F .921(This is useful)5.921 F .944
X(where you want to be able to run versions of Crack on several dif)72 223.2 R
X.944(ferent architectures. If)-.18 F F2(bindir)3.444 E F0 .944(does not)3.444 F
X(exist, a warning will be issued, and the directory)72 235.2 Q 2.5(,c)-.65 G
X(reated.)274.65 235.2 Q(Note:)97 250.8 Q F2(bindir)2.5 E F0
X(defaults to the name)2.5 E F1(generic)2.5 E F0(if not supplied.)2.5 E F2 -1.11
X(Ye)97 266.4 S .859(llow Pages \(NIS\) Users:)1.11 F F0 3.359(Ih)3.359 G .859
X(ave had some queries about how to get Crack running from a)225.435 266.4 R
X.736(YP password \214le.)97 278.4 R .737
X(There are several methods, but by far the simplest is to generate a passwd)
X5.737 F(format \214le by running:-)97 290.4 Q F1(ypcat passwd > passwd.yp)216
X308.4 Q F0(and then running Crack on this \214le.)97 326.4 Q F2 2.5(7. Options)
X72 350.4 R(-network)72 366 Q F0 .775
X(Throws Crack into network mode, in which it reads the)97 378 R F1
X(Scripts/network.conf)3.274 E F0 .774(\214le, splits its)3.274 F .251
X(input into chunks which are sized according to the power of the tar)97 390 R
X.252(get machine, and calls)-.18 F F1(rsh)2.752 E F0 .252(to run)2.752 F 1.217
X(Crack on that machine.)97 402 R 1.216(Options for Crack running on the tar)
X6.217 F 1.216(get machine may be supplied on the)-.18 F .998(command line \(eg\
X: verbose or recover mode\), or in the network.conf \214le if they pertain to \
Xspeci\214c)97 414 R(hosts \(eg:)97 426 Q F1(nice\(\))2.5 E F0(values\).)2.5 E
XF2(-v)72 441.6 Q F0 .851
X(Sets verbose mode, whereby Crack will print every guess it is trying on a per)
X97 441.6 R .85(-user basis.)-.2 F .85(This is a)5.85 F 2.852
X(very quick way of \215ooding your \214lestore.)97 453.6 R 2.852
X(If you unde\214ne the)7.852 F F1(CRACK_VERBOSE)5.353 E F0 2.853(symbol in)
X5.353 F F1(Sources/conf.h)97 465.6 Q F0 2.5(,v)C
X(erbose mode will be permanently disabled.)191 465.6 Q F2(-nvalue)72 481.2 Q F0
X.547(Sets the process to be)97 493.2 R F1(nice\(\))3.047 E F0 .547(ed to)B F3
X(value)3.046 E F0 3.046(,s)C 3.046(ot)278.744 493.2 S .546(hat the switch)
X289.57 493.2 R F1(-n19)3.046 E F0 .546(sets the Crack process to run at)3.046 F
X(the lowest priority)97 505.2 Q(.)-.65 E F2(-rpoint\214le)72 520.8 Q F0 .582
X(This is only for use when running in)97 532.8 R F3 -.37(re)3.082 G(cover).37 E
XF0 3.082(mode. When)3.082 F 3.082(ar)3.082 G .583
X(unning Crack starts pass 2, it periodi-)350.794 532.8 R .997
X(cally saves its state in a \214le named)97 544.8 R F1(point.<pid>)3.497 E F0
X(or)3.497 E F1(point.<hostname>.<pid>)3.497 E F0(depending)3.497 E .89
X(on your naming convention \(see "Installation", above\).)97 556.8 R .891
X(This \214le can be used to recover where you)5.891 F .192
X(were should a host crash.)97 568.8 R .191(Simply invoke Crack in)5.191 F F2
X(exactly)2.691 E F0 .191(the same manner as the last time, with the)2.691 F
X1.212(addition of the)97 580.8 R F1(-rpoint.file.name)3.712 E F0 3.712
X(switch. Crack)3.712 F 1.212(will startup and read the \214le, and jump to)
X3.712 F .013(slightly before where it left of)97 592.8 R 2.513(f. If)-.18 F
X.013(you are cracking a very lar)2.513 F .012
X(ge password \214le, this can save oodles of)-.18 F(time after a crash.)97
X604.8 Q .35(If you are running a)97 620.4 R F3(network)2.85 E F0 .35
X(Crack, then the jobs will again be spawned onto all the machines)2.85 F .181
X(of the original Crack.)97 632.4 R .18
X(The program will then check that the host it is running on is the same as)
X5.181 F .785(is mentioned in the point\214le.)97 644.4 R .786
X(If it is not, it will silently die.)5.786 F .786
X(Thus, assuming that you supply)5.786 F 2.007
X(the same input data and do not change your)97 656.4 R F1(network.conf)4.506 E
XF0 2.006(\214le, Crack should pick up)4.506 F F2(exactly)97 668.4 Q F0
X(where it left of)2.5 E 2.5(f. This)-.18 F(is a bit inelegant, but it')2.5 E
X2.5(sb)-.55 G(etter than nothing at the moment.)325.41 668.4 Q F2 2.5
X(8. Multipr)72 692.4 R(ocessing and parallelism)-.18 E F0 .788(The method of e\
Xrror recovery outlined above causes headaches for users who want to do multipr\
Xocessing)72 708 R .499(on parallel architectures.)72 720 R .499
X(Crack is in no way parallel, and because of the way it')5.499 F 2.998(ss)-.55
XG .498(tructured, readind stdin)409.964 720 R EP
X%%Page: 5 5
X%%BeginPageSetup
XBP
X%%EndPageSetup
X/F0 10/Times-Roman@0 SF(-5-)282.17 48 Q(from shellscript frontends, it is a pa\
Xin to divide the work amongst several processes via)72 84 Q/F1 10/Courier@0 SF
X(fork\(\))2.5 E F0(ing.)A .423
X(The hack solution to get several copies of Crack running on one machine with)
X72 99.6 R/F2 10/Times-Italic@0 SF(n)2.924 E F0 .424(processors at the moment)
X2.924 F 1.546(is to run with the)72 111.6 R F1(CRACK_NETWORK)4.046 E F0 1.545
X(option enabled, and insert)4.045 F F2(n)4.045 E F0 1.545
X(copies of the entry for your parallel)4.045 F .697(machine into the)72 123.6 R
XF1(Scripts/network.conf)3.197 E F0 .697(\214le. If you use the)3.197 F F1(-r)
X3.197 E F0 .697(option in these circumstances how-)3.197 F(ever)72 135.6 Q
X3.172(,y)-.4 G .672(ou will get)99.482 135.6 R F2(n)3.172 E F0 .671(copies of \
Xthe recovered process running, only one of them will have the correct input)
X3.172 F 3(data. I'm)72 147.6 R .5(working on this.)3 F .5(My current solution \
Xis to save the current username in the checkpoint \214le, and)5.5 F .265
X(test it on startup, but doing this)72 159.6 R F2(may)2.765 E F0 .264
X(break your recovery if you supply dif)2.765 F .264
X(ferent input data \(so that the data)-.18 F 1.325(is sorted even slightly dif)
X72 171.6 R 3.826(ferently\). Hohum. If)-.18 F 1.326(you want to use this)3.826
XF F2 1.326(verify username)3.826 F F0(facility)3.826 E 3.826(,u)-.65 G(se)
X468.238 171.6 Q F1(-R)3.826 E F0(in)3.826 E(place of)72 183.6 Q F1(-r)2.5 E F0
X(.)A(As for not using the)72 199.2 Q F1(network.conf)2.5 E F0
X(\214le to provide multiprocessing, I'm working on it.)2.5 E/F3 10/Times-Bold@0
XSF 2.5(9. Notes)72 223.2 R(on fast crypt\(\) implementations)2.5 E F0 .58
X(The stdlib version of the)72 238.8 R F1(crypt\(\))3.08 E F0 .58
X(subroutine is incredibly slow)3.08 F 5.58(.I)-.65 G 3.08(ti)348.58 238.8 S
X3.08(sa)357.22 238.8 S F2(massive)A F0 .58(bottleneck to the execu-)3.08 F .838
X(tion of Crack and on typical platforms that you get at universities, it is ra\
Xre to \214nd a machine which will)72 250.8 R .343
X(achieve more than 50 standard)72 262.8 R F1(crypt\(\))2.842 E F0 2.842(sp)C
X.342(er second.)252.134 262.8 R .342
X(On low-end diskless workstations, you may expect)5.342 F 3.026(2o)72 274.8 S
X3.026(r3p)85.026 274.8 S .526(er second.)104.408 274.8 R .527
X(It was this slowness of the)5.526 F F1(crypt\(\))3.027 E F0 .527
X(algorithm which originally supplied much of the)3.027 F(security)72 286.8 Q/F4
X8/Times-Roman@0 SF(UNIX)2.5 E F0(needed.)2.5 E/F5 7/Times-Roman@0 SF(4)159.472
X282.7 Q F0(However)72 302.4 Q 2.557(,t)-.4 G .057(here are now)116.087 302.4 R
XF1(many)2.557 E F0 .057(implementations of faster versions of)2.557 F F1
X(crypt\(\))2.558 E F0 .058(to be found on the network.)2.558 F
X(The one supplied with Crack v3.2 and upwards is called)72 314.4 Q F1
X(fcrypt\(\))2.5 E F0(.)A F1(fcrypt\(\))72 330 Q F0 .898
X(was originally written in May 1986 by Robert Baldwin at MIT)3.398 F 3.398(,a)
X-.74 G .897(nd is a good version of the)392.516 330 R F1(crypt\(\))72 342 Q F0
X2.837(subroutine. I)2.837 F .338
X(received a copy from Icarus Sparry at Bath University)2.837 F 2.838(,w)-.65 G
X.338(ho had made a couple of)404.28 342 R
X(portability enhancements to the code.)72 354 Q 3.167(Ir)72 369.6 S .667(ewrot\
Xe most of the tables and the KeySchedule generating algorithm in the original)
X81.827 369.6 R F2(fdes-init.c)3.167 E F0 .666(to knock)3.166 F .406(40% of)72
X381.6 R 2.906(ft)-.18 G .406(he execution overhead of)110.402 381.6 R F1
X(fcrypt\(\))2.906 E F0 .407(in the form that it was shipped to me.)2.906 F
X2.907(Ii)5.407 G .407(nlined a bunch of)433.069 381.6 R(stuf)72 393.6 Q 1.11(f\
X, put it into a single \214le, got some advice from Matt Bishop and Bob Baldwi\
Xn [both of whom I am)-.18 F .002(greatly indebted to] about what to do to the)
X72 405.6 R F1(xform\(\))2.502 E F0 .002
X(routine and to the fcrypt function itself, and tidied up)2.502 F 3.185
X(some algorithms.)72 417.6 R 3.185(I've also added more lookup tables and redu\
Xced several formula for faster use.)8.185 F F1(fcrypt\(\))72 429.6 Q F0
X(is now barely recognisable as being based on its former incarnation.)2.5 E
X.562(On a DecStation 5000/200, it is also ~13 times faster than the standard c\
Xrypt \(your mileage may vary with)72 445.2 R .542
X(other architectures and compilers\).)72 457.2 R .542(This speed puts)5.542 F
XF1(fcrypt\(\))3.041 E F0 .541(into the "moderately fast" league of crypt)3.041
XF 2.53(implementations. By)72 469.2 R(using)2.53 E F1(fcrypt\(\))2.53 E F0 .031
X(with Crack, I extracted 135 passwords from my standard 1087 user)2.53 F .114
X(password \214le in a little over 1 hour using 3 networked machines.)72 481.2 R
X.114(This is from a moderately good password)5.114 F(\214le.)72 493.2 Q
X(Why am I saying this sort of thing ? Am I scaremongering ? In a word, yes.)72
X508.8 Q .087(If a fast version of)72 524.4 R F1(crypt\(\))2.587 E F0 .088
X(is wired into a program like Crack it can break a poorly passworded site open)
X2.587 F .249(in minutes.)72 536.4 R .249(There are such programs available, eg\
X: the "Killer Cracker" written by the anonymous "Doctor)5.249 F .326
X(Dissector", with anonymous motives.)72 548.4 R .326
X(It comes with a modi\214ed version of Baldwin')5.326 F 2.826(sf)-.55 G .326
X(crypt, as a MS-DOS)421.922 548.4 R(executable with a GNU copyleft licence.)72
X560.4 Q .239(The point that needs to be hammered home is that unless something\
X is done, and done soon, about the gen-)72 576 R .81
X(eral quality of passwords on)72 588 R F4(UNIX)3.31 E F0 .811
X(systems, then in the near future our doors will be wide open to people)3.31 F
X(who have programs like Crack and questionable motives.)72 600 Q F3 2.5
X(10. Solutions)72 624 R(and Conclusions)2.5 E F0
X(What can be done about this form of attack ?)72 639.6 Q -1(Yo)72 655.2 S 2.754
X(um)1 G .253(ust get a drop-in replacement for the)98.754 655.2 R F1(passwd)
X2.753 E F0(and)2.753 E F1(yppasswd)2.753 E F0 .253
X(commands; one which will stop peo-)2.753 F .79
X(ple from choosing bad passwords in the \214rst place.)72 667.2 R .791
X(There are several programs to do this; Matt Bishop')5.791 F(s)-.55 E F1
X(passwd+)72 679.2 Q F0 .315(and Clyde Hoover)2.815 F -.55('s).37 G F1(npasswd)
X3.365 E F0 .314(program are good examples which are freely available.)2.815 F
X(Consult)5.314 E(an)72 691.2 Q F3(Ar)2.5 E(chie)-.18 E F0
X(database for more details on where you can get them from.)2.5 E .32 LW 144
X708.2 72 708.2 DL/F6 5.6/Times-Roman@0 SF(4)82 716.72 Q F4 .216
X(See: "Password Security)2 3.28 N 2.216(,AC)-.52 G .215
X(ase History" by Bob Morris & Ken Thomson, in the)182.624 720 R/F7 6.4
X/Times-Roman@0 SF(UNIX)2.215 E F4 .215(Programmer Docs.)2.215 F EP
X%%Page: 6 6
X%%BeginPageSetup
XBP
X%%EndPageSetup
X/F0 10/Times-Roman@0 SF(-6-)282.17 48 Q 3.046(Al)72 84 S .546(ittle common-sen\
Xse is all that is required to vet passwords: I enclose a module in the Sources\
X directory)85.046 84 R/F1 10/Times-Italic@0 SF(goodpass.c)72 96 Q F0 1.017
X(which I use in a modi\214ed version of the)3.517 F/F2 10/Courier@0 SF
X(yppasswd)3.517 E F0 1.016(in order to provide some security)3.517 F 6.016(.I)
X-.65 G 3.516(ti)491.034 96 S(s)500.11 96 Q
X(quite heavily customised for use in the UK, but it should be easily portable.)
X72 108 Q(The routine is invoked:)5 E F2
X(char *retval = GoodPass\(char *input\);)177 138 Q F0(where)72 159.6 Q F2
X(input)2.848 E F0 .348(is the password under test, and)2.848 F F2(retval)2.848
XE F0 .349(will be set either to NULL \(if the password is OK\))2.848 F .436
X(or to a diagnostic string which says what is wrong with the password.)72 171.6
XR .435(It is far less complex than a system)5.435 F .442(such as)72 183.6 R F1
X(passwd+)2.942 E F0 2.942(,b)C .442(ut still ef)151.186 183.6 R .443
X(fective enough to make a password \214le withstand)-.18 F F2(Crack)2.943 E F0
X5.443(.I)C 2.943(tw)432.238 183.6 S .443(ould be nice if)445.181 183.6 R .959
X(an or)72 195.6 R .959(ganisation \(such as)-.18 F/F3 10/Times-Bold@0 SF(CER)
X3.459 E(T)-.35 E F0 3.459(?\) could)B .958(be persuaded to supply skeletons of)
X3.459 F F1(sensible)3.458 E F0 .958(passwd commands)3.458 F .445
X(for the public good, as well as an archive of security related utilities)72
X207.6 R/F4 7/Times-Roman@0 SF(5)348.68 203.5 Q F0 .446(on top of the excellent)
X355.125 207.6 R F2(COPS)2.946 E F0 5.446(.H)C(ow-)488.45 207.6 Q(ever)72 219.6
XQ 3.216(,f)-.4 G(or)97.856 219.6 Q/F5 8/Times-Roman@0 SF(UNIX)3.216 E F0 .716(\
Xsecurity to improve on a global scale, we will also require pressure on the ve\
Xndors, so that)3.216 F(programs are written correctly from the beginning.)72
X231.6 Q .32 LW 144 708.2 72 708.2 DL/F6 5.6/Times-Roman@0 SF(5)82 716.72 Q/F7 8
X/Courier@0 SF(COPS)2 3.28 M F5(is available for anonymous FTP from)2 E/F8 8
X/Times-Italic@0 SF(cert.sei.cmu.edu)2 E F5(\(128.237.253.5\) in)2 E F8(~/cops)2
XE EP
X%%Trailer
Xend
X%%EOF
END_OF_FILE
if test 37992 -ne `wc -c <'Docs/README.ps'`; then
echo shar: \"'Docs/README.ps'\" unpacked with wrong size!
fi
# end of 'Docs/README.ps'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone

0 new messages