home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-09-22 | 50.7 KB | 1,747 lines |
- Newsgroups: comp.sources.misc,alt.sources,alt.security
- From: aem@aber.ac.uk (Alec David Muffett)
- Subject: v23i003: crack - The Password Cracker, version 3.3c, Part03/05
- Message-ID: <1991Sep22.050741.13666@sparky.imd.sterling.com>
- X-Md4-Signature: 43ee50b0660b46e79fff4bf54ebf1787
- Date: Sun, 22 Sep 1991 05:07:41 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: aem@aber.ac.uk (Alec David Muffett)
- Posting-number: Volume 23, Issue 3
- Archive-name: crack/part03
- Environment: UNIX
- Supersedes: crack: Volume 22, Issue 49-52
-
- #! /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 5)."
- # Contents: APPENDIX CHANGES Sources/crack-pwc.c
- # Wrapped by aem@aberda on Fri Sep 20 12:26:54 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'\" \(13138 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 crackers
- 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 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
- XAlso, Brian Tompsett (bct@uk.ac.hull.cs), for pointing me to the now
- Xfamous v3.2 bug, and for numerous suggestions and patches, not to
- Xmention the enormous amount of debugging information he's sent me about
- XCrack v3.3. To him should go the prize for "Most Vociferous Beta
- XTester".
- X
- XAnd M.Maclaren, for pointing me towards some changes I could make to toBA64.
- X
- XAnd finally, to my girlfriend Gilly, for her occasional large doses of
- Xsanity. 8-)
- 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 13138 -ne `wc -c <'APPENDIX'`; then
- echo shar: \"'APPENDIX'\" unpacked with wrong size!
- fi
- # end of 'APPENDIX'
- fi
- if test -f 'CHANGES' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CHANGES'\"
- else
- echo shar: Extracting \"'CHANGES'\" \(12874 characters\)
- sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
- XChanges file:-
- X
- X-> Crack 2.7
- X
- X* Not documented as were expected to be internal only. Ha bloody ha.
- X
- X-> Late July 1991
- X
- X* Posted Crack v2.7 to the net and was immediately swamped with email
- X
- X* Arranged archiving @ wuarchive.wustl.edu - ~/packages
- X
- X-> 31 July 1991 v3.1
- X
- X* First release of Crack 3.1.
- X
- X* Decided to post future releases with fcrypt() installed.
- X
- X* Put another 100eps on xform() by using direct addressing of Sn[]
- X arrays in the main loop of xform()
- X
- X* Oddly enough, using a direct addressing trick instead of (*dp STEP)
- X slows things down on the 5000/200 - I'll leave it as it was.
- X
- X-> 1 Aug 1991 v3.1b
- X
- X* Modified Scripts/joinfiles to filter out locked/null account passwords
- X - This fixes a load imbalance on Crack -network. O/P > crack.inital.
- X
- X* Removed CRACK_USERNAME as a option - make it mandatory, it's silly to
- X bother turning it off. Ditto CRACK_USERNAME2
- X
- X* Modified method of argument parsing in Crack script for more
- X flexibility
- X
- X* Added a few extra comments to Crack
- X
- X* Changed Scripts/crack.mf for clarity
- X
- X* Crack-pwc now uses linked lists for dictionary handling - dicts can be
- X read in until you run out of memory and it crashes. Fun, eh ?
- X
- X* Since linked list handling uses pushdown lists, I reversed order of
- X sort in Scripts/makedicts to counteract dictionary reversal - passwords
- X are more common towards the start of the alphabet. Lazy or what ?
- X
- X* Removed CRACK_WARN/CRACK_NULLED as options as these jobs are done by
- X Scripts/joinfiles now. Code left in crack-pwc though, just in case.
- X
- X* Crack-pwc now creates the output file, not Crack
- X
- X* Crack-pwc now does checkpointing. Will need to write recover code
- X soon.
- X
- X* Renamed output files to "out.*" instead of "crack.*" - also uses the
- X same PID
- X
- X* Crack-pwc now uses getopt()
- X
- X* Put -V (verbose) option in : defining CRACK_VERBOSE is still necessary
- X to be able to use this option, however. It generated a 1Mb file in 90
- X seconds though, so I'm gonna keep it switched off, personally.
- X
- X* Changed CRACK_NICE to -Nnumber option
- X
- X* Changed crack-pwc so that input is from stdin _or_ "-Ifilename"
- X
- X-> August 2 1991 v3.1b
- X
- X* Paranoia is cracking me up. in "Crack" when I invoke "-network" with
- X the crack-pwc >& /dev/null < /dev/null - nothing happens. Well, rather
- X nothing happened. Until I tried it again this morning. Now it works.
- X Hmmmmmmm.
- X
- X* Checkpointing recover code in now spattered all over crack-pwc.c
- X
- X* The whole idea is that you invoke Crack EXACTLY as before, with the
- X attition of the "-Rpoint.filename.pid" switch.
- X
- X* If it's not a network Crack, the job will restart where it left off.
- X
- X* If it IS a network Crack, the whole "rsh" schmeer will take place
- X again, but "crack-pwc" will be left running ONLY on the machine named in
- X the pointfile. If you need to run it on a different host, change the
- X name of the host in the pointfile. This could cause problems tho.
- X
- X* Fixed Scripts/Crack.network to parse arguments and allow network.conf
- X to contain per-hostname Crack arguments.
- X
- X* Fixed Scripts/RCrack to support the above
- X
- X* Started reworking README in ms macros
- X
- X-> August 5 1991 v3.1b
- X
- X* Totally rewritten README
- X
- X* Doublechecked fcrypt() still works on Sun 4/330 - works fine.
- X
- X* Tidied fcrypt() configuration symbols into conf.h and reworked some
- X comments in conf.h for readability
- X
- X-> 7/8 Aug 1991 v3.1b
- X
- X* *!*!*!*!*!* LOWERCASED ALL OPTION SWITCHES
- X
- X* Added new -R as distinct from -r in that it recovers with a username
- X check.
- X
- X* Introduced Sources/crack-port.c with a version of gethostname() which
- X uses uname() on SysV like systems. Use CRACK_UNAME switch in
- X Sources/conf.h to enable this.
- X
- X* Edited Scripts/RCrack to put 'rsh' into a variable name for easier
- X access to SysV or SCO ppl who want to change it to 'rcmd'.
- X
- X* Fixed up the README a bit more
- X
- X* Redid CRACK_PW_TRUNCATE to be more clever, as CRACK_PW_VERIFY
- X
- X-> 9 Aug 1991 v3.1c
- X
- X* Removed library type stuff from Sources/Makefile - Chris Lewis pointed
- X out problems this would generate with portability.
- X
- X* Batching alternative version of Crack script written in 'sh'
- X
- X* Crack.sh finished and documented (slightly)
- X
- X* Fixed remaining bug left from lowercasing switches... next time I'll
- X be quicker to check my getopt() string
- X
- X* Did a better MANIFEST file
- X
- X* Found a bug in Scripts/crack.mf - there was no target for $(DICTSRC) -
- X fixed. This showed up when 'makekit' dropped the bad_pws.dat file
- X
- X-> 12 Aug 1991 v3.2a
- X
- X* Putting a simplified numerics pass into the preprocessor to create an
- X additional dictionary.
- X
- X* Got a mail message from a guy telling me that I should sort&uniq my
- X dictionaries - evidently he hasn't been reading the shellscripts, just
- X the code. Ah well.
- X
- X* Revamped docs for things I'd missed
- X
- X* Made o/p of pwc in Crack a variable - that way I can select it at the
- X top of the file
- X
- X* Fixed a bug in GetPoint - didnt always return NULL when it should
- X
- X* Found a pointing bug in Pass2 - if data HAD changed, program could
- X have walked off the end of the linked list.
- X
- X* Emptied network.conf for distribution
- X
- X* Bought the new 'Jam' CD compilation
- X
- X* Attempted to wrap progs up for testing.
- X
- X-> Aug 19th 1991 v3.2a
- X
- X* Got back from Cropredy with a list of things to do.
- X
- X* Created new way of putting dicts into crack - just drop them into
- X DictSrc and the program should take care of the rest of it. Saves
- X editing files and with dictionaries.tar.Z now available, it will save
- X a lot of bother for people - they just have to drop them into the
- X directory. Updated docs accordingly.
- X
- X* Created APPENDIX file for people who query my methods and sanity.
- X
- X* added personalisation to conf.h for my purposes only. Also, according
- X to one guy, his system barfed the comments in conf.h because they
- X started on the same line as a #undef.
- X
- X* Crack-pp now ignores dictionary lines beginning with '#' - this allows
- X the Klein dictionaries to be dropped straight into the DictSrc
- X directory.
- X
- X* Crack-pwc now tries a username+reversed username permutation that
- X someone suggested, I've forgotten who and it's buried in 3Mb of email.
- X
- X* Redid the manifest (again) .
- X
- X* Modified CRACK_TRAILING to do a leading-digits pass.
- X
- X* Crack-pwc.c now skips empty dictionaries.
- X
- X* I found that in using wildcards in Scripts/crack.mf, I created a
- X problem. The DICTSRC target contined a member DictSrc/* which was
- X always out of date, because it was never made when I called 'make
- X dictstamp' - Make looks for something literally called 'DictSrc/*' and
- X not the individual files. Hopefully, removing the (blank) dependency
- X for $(DICTSRC) will fix this. Subtle and annoying.
- X
- X-> Aug 20th 1991 v3.2a
- X
- X* Tagged a few extra comments onto APPENDIX
- X
- X-> Aug 21st 1991 v3.2a
- X
- X* Cleaned up a bit of the README files. Ready for release.
- X
- X* Last minute check - found that using 'gcc' as opposed to 'cc' made
- X fcrypt() slow and incompatible with the standard crypt() - this is not
- X nice.
- X
- X-> Aug 22nd 1991 v3.2a
- X
- X* First bug reports coming back. AIX doesnt like fcrypt(), possibly due
- X to putting numbers > 255 in a u_char in fcrypt() - fixed this.
- X
- X-> Aug 23rd 1991 v3.2a
- X
- X* Second major bug report in "plaster" - should not assume '.' is in the
- X path, is a security hole. Fixed.
- X
- X* Apparently fixing the >8bit bytes does not help fcrypt() on AIX - it
- X still fails. Bother.
- X
- X-> Aug 27 1991 v3.2b
- X
- X* Put newlines in AWK script embedded in Scripts/RCrack - apparently
- X some awks need linebreaks
- X
- X* Pointfile now contains a datestamp obtained from ctime() - saves on
- X headaches.
- X
- X* crack-fcrypt.c: removed use of R[] block by finding the ONE place it
- X was referenced and replacing it with a modified reference to L[].
- X This means that the new L[] is the old R[] + L[]. There are no more
- X contiguity problems, so 'gcc' now works, but it is slower than the
- X output of 'cc' on my DECStation. Caveat Emptor.
- X
- X* Crack rewritten in 'sh'
- X
- X* Scripts rewired for greater flexibility
- X
- X-> 28 Aug 1991 v3.3a
- X
- X* Fixed bug in init() stuff - a tmpE array was declared with size [32]
- X and not [48] - this was causing problems on a Sun 3, causing coredumps.
- X
- X* Clarified Endianitis in conf.h - definitely traced to fcrypt problems
- X on RS/6000 and HP's.
- X
- X* Added Chris Stassens (?) improvements to the load balancing algorithm
- X in Crack.network
- X
- X* Wired -N switch into crack-pwc to prevent Crack.network working unless
- X CRACK_NETWORK defined.
- X
- X-> 29 Aug 1991 v3.3a
- X
- X* Fixed up a few filenames which > 14 chars long. Probably missed a
- X few. Hohum.
- X
- X* Added env variable CRACK_OUT to Crack, as a directory to put output files.
- X
- X* Spent rest of day playing with Oraperl.
- X
- X-> 29 Aug 1991 v3.3a
- X
- X* Fixed up crack-pp dictionary preprocessor to be more flexible about
- X when it generates plurals... I originally restricted it to lowercase
- X words in order to keep it under control, but it has proved so horribly
- X successful that it needs extending.
- X
- X* Put "umask 077 in Crack"
- X
- X* Touched up README.FIRST in anticipation of the next release.
- X
- X* Touched up README.
- X
- X-> 3rd Sep 1991 v3.3a
- X
- X* crack-pwc now unlinks "die" and "point" files on exit
- X
- X* Scripts/do_join now traps passwords with '*' '!' and SPCs anywhere
- X in the string, and logs them to file.
- X
- X* Found some people are posting patches to comp.sources.bugs without
- X telling me all about it. Most annoying, but at least it means that
- X the fixes are going out. Hohum. I suppose you must get used to it if
- X you go round casting your pearls before swine... 8-)
- X
- X-> 4th Sep 1991 v3.3a
- X
- X* Crack now can run in foreground mode (-f option) :- useful for
- X invocation from other programs. Unlike the patches which other ppl
- X supply to do this job, Crack 3.3 actually does a bit of sanity
- X checking of arguments (eg: no foreground mode for Crack -network),
- X and it warns of the importance of the out.init.$$ file.
- X
- X* Crack-pp now does somewhat better pluralisation. If any linguists
- X dare tell me about the weak points and exceptions, they can go stuff
- X themselves. 8-)
- X
- X* Crack.network now distributes load on basis of salted lines -
- X splitting salts evenly over the network. This satisfies some pedants,
- X and to be honest, even I was quite surprised at the way that the load
- X rebalances.
- X
- X* Changes name of point.<host>.<pid> to pnt.<host>.<pid>
- X
- X* Put feedback code into crack-pwc
- X
- X* Created simple feedback script in Scripts directory.
- X
- X-> 4th Sep 1991 v3.3a
- X
- X* Tidied up feedback code in crack-pwc.c
- X
- X* Put all runtime diagnostic files into directory 'Runtime'
- X
- X* Got rid of the MCB pass - it never showed anything up anyway. No
- X doubt someone will attack me for this though...
- X
- X* Inserted feedback-filter code into Crack
- X
- X* Had lunch in the arts centre with my sister.
- X
- X* After a few hours fighting with fcrypt(), basically inlining the whole
- X of toBA64(), I measure fcrypt() as 15 times faster than standard.
- X Found a compiler weirdness too - read the bottom of the XForm()
- X function in crack-fcrypt.c
- X
- X-> 5th Sep 1991 v3.3a
- X
- X* Fixed a bug in crack-lib.c - Initcap wasn't working properly
- X
- X* Fixed up feedback mode to lookup guessable and non-guessable
- X passwords, and wired code into do_join instead of independent utility.
- X
- X* NEW FORMAT NETWORK.CONF - allows specification of different usernames
- X for 'rsh', and ability to specify a copy of Crack OTHER than that you
- X are using.
- X
- X* Created a slightly duboius Scripts/shadmrg script, to merge
- X /etc/shadow on Sys V systems
- X
- X* Fixed CRACK_GECOS so that it took in info AFTER a ','
- X
- X-> 9th Sep 1991 v3.3a
- X
- X* reinstated MCB pass as reverse forced capitalised
- X
- X-> 11th Sep 1991
- X
- X* Installed serries of patches back from bct@hull.cs, lots of minor
- X for protability probs and a new feature - smart rsh-ing.
- X
- X-> 13th Sep 1991
- X
- X* Okay, I won't go into detail because its horribly complex, but at
- X least simpler that Brian's solution (grin)... Crack can do remote
- X processing on machines without NFS by invoking them with the '-f'
- X option (specified in network.conf) and backgrounding the rsh on the
- X server, rather than letting it exit. Functionally identical but a bit
- X neater.
- X
- X* Trivial bugfix - crack-pp no longer exits when it finds it cannot read
- X a source dictionary. It just warns about it.
- X
- X-> Wed 18th Sep 1991
- X
- X* Got Gilly to proofread the README file... tidied it up quite a bit.
- X
- X* Got some more back off BCT about the state of Crack 3.3c. There was a
- X fencing error in saltcount and it RCrack needed a sanity check
- X installing to prevent it from rshing to another machine with no data
- X to crack. Have installed similar trap in Crack.network. Removed
- X reference to /dev/tty in RCrack's big awk script.
- X
- X* Found bugs in the pluralisation algorithms, mostly to do with over
- X zealout fprintfs. Reimplemented more elegantly.
- X
- X-> 19th Sep 1991
- X
- X* Added/documented guess2fbk script
- X
- X-> 20th Sep 1991
- X
- X* Packaged v3.3 up ready to go.
- X
- X* Had a great idea.
- X
- X* Started work on v4.0.
- END_OF_FILE
- if test 12874 -ne `wc -c <'CHANGES'`; then
- echo shar: \"'CHANGES'\" unpacked with wrong size!
- fi
- # end of 'CHANGES'
- 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'\" \(21449 characters\)
- sed "s/^X//" >'Sources/crack-pwc.c' <<'END_OF_FILE'
- X#include "crack.h"
- X
- X#ifdef hpux /* You could add your particular unix variant here */
- Xchar rcmd[] = "remsh";
- X#else
- Xchar rcmd[] = "rsh";
- X#endif
- X
- Xchar version[] = "3.3c"; /* version of prog */
- Xchar runtime[] = "Runtime";
- Xchar feedback_string[] = "!fb!";
- 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 freely redistributable PROVIDED
- X * 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; /* bool flag */
- X char *filename; /* where we got it from */
- X char *passwd_txt; /* plaintext of password */
- X struct passwd passwd; /* ...guess... */
- X struct USER_ENTRY *across; /* line of users with same salt */
- X struct USER_ENTRY *next; /* next users with different salt */
- X};
- X
- Xstruct DICT_ENTRY
- X{
- X char *word; /* simple linked list */
- X struct DICT_ENTRY *next;
- X};
- X/* Variable declarations */
- X
- Xstruct USER_ENTRY *user_root; /* root of the USER linked list */
- X
- Xint recover_bool; /* we are trying to recover from a crash */
- Xint verify_recover; /* we will doublecheck usernames on recovery */
- Xint rpid; /* pid we are recovering */
- Xchar rdict[STRINGSIZE]; /* dict we are recovering */
- Xchar rusername[STRINGSIZE]; /* username we are recovering */
- Xchar rhostname[STRINGSIZE]; /* hostname we are recovering on */
- Xint rusercount; /* count of user we are recovering at;
- X * strictly, this is the line of the user we
- X * are recovering */
- 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 */
- Xchar feedbackfile[STRINGSIZE]; /* guess */
- Xchar hostname[STRINGSIZE];
- 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 long t;
- X
- X if (!(fp = fopen (pointfile, "w")))
- X {
- X perror (pointfile);
- X return;
- X }
- X time (&t);
- 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 fprintf (fp, "last pointed: %s", ctime (&t));
- 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 -> passwd_txt = 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 = atoi (p);
- X p = PWSkip (p);
- X retval -> passwd.pw_gid = atoi (p);
- 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 salt[0] = salt[1] = '*';
- 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 (strchr (ptr, '*') ||
- X strchr (ptr, '!') ||
- X strchr (ptr, ' '))
- X {
- X Log ("User %s (in %s) has a locked password:- %s\n",
- X new_element -> passwd.pw_name,
- X new_element -> filename,
- X new_element -> passwd.pw_passwd);
- 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#ifdef CRACK_PRINTOUT /* prevents (some) appearances in coredumps */
- X eptr -> passwd_txt = Clone (guess); /* essential to FeedBack */
- X#endif
- X
- X Log ("Guessed %s%s (%s in %s) [%s] %s\n",
- X (eptr -> passwd.pw_uid ? "" : "ROOT PASSWORD "),
- 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#ifdef CRACK_PRINTOUT2
- X eptr -> passwd.pw_passwd
- X#else
- X ""
- X#endif /* CRACK_PRINTOUT2 */
- 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 = ' ';
- X }
- X if (ptr2 = (char *) strchr (ptr, ',')) /* trim off more junk */
- X {
- X *ptr2 = ' ';
- 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); /* puff, puff, puff, pant pant */
- 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"); /* almost there */
- X exit (0);
- X }
- X }
- X /* at bloody last */
- 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
- Xvoid
- XFeedBack (unguessed)
- X int unguessed;
- X{
- X register FILE *fp;
- X static char fmt[] = "%s:%s:%s:%s\n";
- X register struct USER_ENTRY *head;
- X register struct USER_ENTRY *arm;
- X
- X Log ("Doing feedback file.\n");
- X
- X fp = (FILE *) 0;
- X
- X for (head = user_root; head; head = head -> next)
- X {
- X for (arm = head; arm; arm = arm -> across)
- X {
- X if (arm -> done)
- X {
- X if (!fp) /* horrible little hack - I love it */
- X {
- X if (!(fp = fopen (feedbackfile, "w")))
- X {
- X perror (feedbackfile);
- X return;
- X }
- X Log ("Feedback file opened.\n");
- X }
- X fprintf (fp, fmt, feedback_string, arm -> passwd.pw_passwd,
- X "Y", arm -> passwd_txt);
- X } else
- X {
- X if (unguessed)
- X {
- X if (!fp) /* and again !!! heheheheheheh */
- X {
- X if (!(fp = fopen (feedbackfile, "w")))
- X {
- X perror (feedbackfile);
- X return;
- X }
- X Log ("Feedback file opened.\n");
- X }
- X /* I think I'm going slightly warped */
- X fprintf (fp, fmt, feedback_string, arm -> passwd.pw_passwd,
- X "N", "");
- X }
- X }
- X
- X }
- X }
- X fclose (fp);
- X Log ("Done feedback file.\n");
- X return;
- X}
- X
- Xint
- Xmain (argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int i;
- X FILE *fp;
- X char *file;
- X char *crack_out;
- X int uerr;
- X extern int optind;
- X extern char *optarg;
- X char rshother[STRINGSIZE];
- X int foreground_bool = 0;
- X int rshother_bool = 0;
- X int feedback_bool = 0;
- X int network_bool = 0;
- 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, "fFNvU:i:r:R:n:")) != EOF)
- X {
- X switch (i)
- X {
- X case 'N':
- X#ifndef CRACK_NETWORK
- X Log ("Called remotely but not compiled with CRACK_NETWORK symbol\n");
- X Log ("Exiting...\n");
- X exit (1);
- X#else
- X network_bool = 1;
- X#endif
- X break;
- X case 'U':
- X strcpy (rshother, optarg);
- X rshother_bool = 1;
- X break;
- X case 'F':
- X feedback_bool = 1;
- X break;
- X case 'f':
- X foreground_bool = 1;
- X break;
- X case 'v':
- X verbose_bool = 1;
- X break;
- X case 'n':
- X nice (atoi (optarg));
- 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 case 'i':
- X if (!freopen (optarg, "r", stdin))
- X {
- X perror (optarg);
- X exit (1);
- X }
- X /*
- X * If we unlink this file here it effectively hides it, as well
- X * as preventing the file systems all over the network getting
- X * gummed up with crud. Only delete a tmp file which matches out
- X * standard template. Anything else might be a user's own file
- X * bct@hull.cs
- X */
- X
- X if (strcmp (optarg, "/tmp/pw.", 8))
- X {
- X unlink (optarg);
- X }
- 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 [-NFfv] [-ifile] [-nn] [-<R|r>file] [-Uname] dictfile [...]\n",
- X argv[0]);
- X exit (1);
- X }
- X crack_out = (char *) getenv ("CRACK_OUT");
- X
- X if (!crack_out)
- X {
- X crack_out = ".";
- X }
- X#ifdef CRACK_NETWORK
- X sprintf (opfile, "%s/out.%s.%d", crack_out, hostname, pid);
- X sprintf (diefile, "%s/die.%s.%d", runtime, hostname, pid);
- X sprintf (pointfile, "%s/pnt.%s.%d", runtime, hostname, pid);
- X sprintf (feedbackfile, "%s/fbk.%s.%d", runtime, hostname, pid);
- X#else
- X sprintf (opfile, "%s/out.%d", crack_out, pid);
- X sprintf (diefile, "%s/die.%d", runtime, pid);
- X sprintf (pointfile, "%s/pnt.%d", runtime, pid);
- X sprintf (feedbackfile, "%s/fbk.%d", runtime, pid);
- X#endif /* CRACK_NETWORK */
- X
- X if (!foreground_bool)
- 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 }
- X /*
- X * If we are given a "-f" flag from across the network we must still make
- X * a die file so the remote machine can still find the right process to
- X * kill with a plaster bct@hull.cs
- X */
- X
- X if (network_bool || !foreground_bool)
- X {
- X if (!(fp = fopen (diefile, "w")))
- X {
- X perror (diefile);
- X exit (1);
- X }
- X fprintf (fp, "#!/bin/sh\n");
- X
- X#ifdef CRACK_NETWORK
- X /*
- X * Use the "-n" option on "rsh" to avoid problems of input streams
- X * attached to remote processes. See man page for rsh bct@hull.cs
- X */
- X
- X if (rshother_bool)
- X {
- X fprintf (fp, "%s %s -n -l %s kill -TERM %d", rcmd, hostname,
- X rshother, pid);
- X } else
- X {
- X fprintf (fp, "%s %s -n kill -TERM %d", rcmd, hostname, pid);
- X }
- X#else
- X fprintf (fp, "kill -TERM %d", pid);
- X#endif /* CRACK_NETWORK */
- X fprintf (fp, " && rm $0\n");
- X fclose (fp);
- X chmod (diefile, 0700);
- 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#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 ("This could be due to byte ordering problems - see the comments in Sources/conf.h\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#ifdef CRACK_PRINTOUT
- X if (feedback_bool)
- X {
- X FeedBack (0);
- X }
- X#endif /* CRACK_PRINTOUT */
- 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#ifdef CRACK_PRINTOUT
- X if (feedback_bool)
- X {
- X FeedBack (0);
- X }
- X#endif /* CRACK_PRINTOUT */
- X }
- X
- X Log ("Finished. Tidying up files...\n");
- X if (network_bool || !foreground_bool)
- X {
- X unlink (diefile);
- X }
- X unlink (pointfile);
- X
- X#ifdef CRACK_PRINTOUT
- X if (feedback_bool)
- X {
- X FeedBack (1);
- X }
- X#endif /* CRACK_PRINTOUT */
- X Log ("Done.\n");
- X return (0);
- X}
- END_OF_FILE
- if test 21449 -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
- echo shar: End of archive 3 \(of 5\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 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...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-