home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume22
/
crack
/
part02
< prev
next >
Wrap
Text File
|
1991-08-23
|
59KB
|
2,932 lines
Newsgroups: comp.sources.misc
From: Alec David Muffett <aem@aber.ac.uk>
Subject: v22i050: crack - The Password Cracker, version 3.2a, Part02/04
Message-ID: <1991Aug23.150416.999@sparky.IMD.Sterling.COM>
X-Md4-Signature: 14cb360e7ff676b07065904a1d45e698
Date: Fri, 23 Aug 1991 15:04:16 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: Alec David Muffett <aem@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: aem@aber.ac.uk JANET: aem@uk.ac.aber BITNET: aem%aber@ukacrl
XUUCP: ...!mcsun!ukc!aber!aem ARPA: aem%uk.ac.aber@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 (aem@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 (mattson@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 (aem@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
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...