home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume23 / crack / part03 < prev    next >
Encoding:
Text File  |  1991-09-22  |  50.7 KB  |  1,747 lines

  1. Newsgroups: comp.sources.misc,alt.sources,alt.security
  2. From: aem@aber.ac.uk (Alec David Muffett)
  3. Subject:  v23i003:  crack - The Password Cracker, version 3.3c, Part03/05
  4. Message-ID: <1991Sep22.050741.13666@sparky.imd.sterling.com>
  5. X-Md4-Signature: 43ee50b0660b46e79fff4bf54ebf1787
  6. Date: Sun, 22 Sep 1991 05:07:41 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: aem@aber.ac.uk (Alec David Muffett)
  10. Posting-number: Volume 23, Issue 3
  11. Archive-name: crack/part03
  12. Environment: UNIX
  13. Supersedes: crack: Volume 22, Issue 49-52
  14.  
  15. #! /bin/sh
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 3 (of 5)."
  21. # Contents:  APPENDIX CHANGES Sources/crack-pwc.c
  22. # Wrapped by aem@aberda on Fri Sep 20 12:26:54 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'APPENDIX' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'APPENDIX'\"
  26. else
  27. echo shar: Extracting \"'APPENDIX'\" \(13138 characters\)
  28. sed "s/^X//" >'APPENDIX' <<'END_OF_FILE'
  29. XOdds and sods that I thought are interesting:
  30. X
  31. X********
  32. X
  33. XSeveral people have asked me why I don't write Crack so that it
  34. Xdistributes dictionaries over the network and hacks the same password
  35. Xfile on each machine, as opposed to spreading users over the network and
  36. Xusing the same dictionaries.
  37. X
  38. XThere are several reasons for this, which I will outline.
  39. X
  40. XThe reasoning that spreading the dictionaries over the network is faster
  41. Xis correct in the case of cracking the passwords of ONE user - it is
  42. Xmost efficient to run different dictionaries on him on several machines,
  43. Xand you will break his password eventually.
  44. X
  45. XScaling this by a factor of 'n' users causes problems.  Firstly, if a
  46. Xmachine guesses one persons password, it must inform all others on the
  47. Xnetwork not to waste time cracking him, but to get on with the other
  48. Xusers.  This is difficult and nasty.
  49. X
  50. XSecondly, it is not what Crack was designed to do.  The name "Crack" is
  51. Xactually a misnomer - Crack really ought to be called "Passwdcheck" or
  52. Xsomething similar, but such names lack sex appeal.
  53. X
  54. XCrack is not a program designed to break the password of every user in
  55. Xthe file.  Rather, it is designed to find weak passwords in the file, by
  56. Xattacking those sorts of bad passwords which are most likely to be used,
  57. Xin the order in which they would most easily be found (ie: are most
  58. Xlikely to be used by a moronic user).
  59. X
  60. XCrack is not designed to break user passwords; it is designed to break
  61. Xpassword files.  This is a subtle but important distinction.
  62. X
  63. XIf you want to break into a safe, you do not take a hammer at every bit
  64. Xof it in turn; instead, first you try some simple combinations, then you
  65. Xtry blowing the hinges off, then you get out an acetylene torch and go
  66. Xfor the bolt.  If that doesnt work, THEN you start on the walls.  You go
  67. Xfor the bits which are most likely to be weak first.
  68. X
  69. XConsider a password file with 'n' users in it.  Say that your serial
  70. Xpassword cracker uses a dictionary of 1000 words, and tries each word 6
  71. Xways (upper/lower/mixed case, permuted with forwards/backwards)
  72. X
  73. XAlso consider that out of that 1000 users, only one (the last one) has a
  74. Xguessable password - "fred".
  75. X
  76. XAlso say that it takes time 'T' seconds to encrypt a word.
  77. X
  78. XIf you use the "try each user in turn" method, like the COPS password
  79. Xcracker, you will have to wait for a time:-
  80. X
  81. X    999 users * 1000 words * 6 ways * T = 5994000 T seconds
  82. X
  83. Xbefore you get to that last user.  Spreading this load around on a
  84. Xnetwork only alleviates the number of words to be searched (divides them
  85. Xby the number of machines you are working on).
  86. X
  87. XThus, if you use 10 machines, the machine which will guess "fred" will
  88. Xget to that last user in:-
  89. X
  90. X    999 * (1000 / 10) * 6 ways = 599400 T seconds.
  91. X
  92. XAlternatively you can try it the Crack way - "fred" is a word which
  93. Xappears in a forwards dictionary.  You will only wait:-
  94. X
  95. X    999 users * 1000 words * 1st way * T = 999000 T seconds
  96. X
  97. Xto get to that user.  Now split the _USERS_ across 10 machines:-
  98. X
  99. X    (999 / 10) users * 1000 words * 1st way = 99900 T seconds
  100. X
  101. XTo get to his password, in ONLY 17% of the time taken by networking
  102. Xusing the serial cracking method.  This is only a boundary case, but I
  103. Xhope I have illustrated the concept.
  104. X
  105. X********
  106. X
  107. XCrack has several other optimisations because of its structured password
  108. Xguesses.  The figures below are entirely empirical, but I reckon that
  109. Xthey're as good as any:
  110. X
  111. XThe first pass that Crack makes is over the user data user information
  112. Xgleaned from the users' password field.  In my test file, this gets
  113. Xabout 3% of the passwords (out of a total of 11% guessed).  This pass
  114. Xalso completes the quickest of all, working as it does from a very small
  115. Xamount of data, but one which is very frequently used for passwords.
  116. X
  117. XMy test password file is 1150 users big, and the first pass completes in
  118. Xa little over 2 minutes.  In that time Crack gets 35 accounts.
  119. X
  120. XThe first sweep of the second pass, consisting of lowercase dictionary
  121. Xwords, gets about another 5% of the passwords.  This means that, for our
  122. X1150 users, we have now cracked a cumulative total of 91 accounts.  The
  123. Xlength of the first sweep depends on how much CPU and how many
  124. Xdictionaries I supply, but using the Ultrix /usr/dict/words and my
  125. Xbad_pws.dat, over 4 CPUs, it doesn't take much more that a couple of
  126. Xhours.
  127. X
  128. XFor the further sweeps, the percentages cracked per sweep tail off, 2%,
  129. X1%, 0.5%...  But they are the people with fairly exotic passwords, and
  130. Xit's only common sense that that they will take some time to crack.
  131. X
  132. X********
  133. X
  134. XThere is one more major optimisation that I haven't mentioned.  Because
  135. Xof the way the UNIX crypt() algorithm works, each encryption is "salted"
  136. Xwith a two letter sequence which is stored as the first two characters
  137. Xof the encrypted password.  This salting means that the word "fred" can
  138. Xbe encrypted and appear in a password file in (literally) thousands of
  139. Xdifferent ways - so long as each encryption has a different salt.
  140. X
  141. XHence, it makes sense to do things in this manner:
  142. X
  143. X1) sort and group the input data by encryption salt.
  144. X2) for each different groups' encryption salt
  145. X    * get a dictionary word
  146. X    * encrypt it using that salt (This is the time consuming bit)
  147. X    * compare the encryption with each member of the group with that salt
  148. X    * if it matches, you have guessed that users password.
  149. X
  150. XThis knocks (empirical guesswork time again) up to one third of the
  151. Xdictionary encryptions off - thus saving you 0.3 of the time all the
  152. Xdictionary sweeps would ordinarily take.  You can work out this figure
  153. Xyourself: Crack gives this statistic when it says
  154. X
  155. X    pwc: Loaded 'n' password entries into 'm' salted lines.
  156. X
  157. Xso you can work out the percentage of users who have the same salt:-
  158. X
  159. X            x = (m / n) * 100
  160. X
  161. Xand hence the percentage of encryption time that you save = (100 - x).
  162. X
  163. X********
  164. X
  165. XListening to the REM album 'Green' on the way back from the Cropredy
  166. Xfolk festival yesterday, whilst I was thinking over things to do to
  167. XCrack, and I was struck (not for the first time) by the words of the
  168. Xfirst verse to 'World Leader Pretend':-
  169. X
  170. X    I sit at my table, and wage war upon myself.
  171. X    It seems like it's all, it's all for nothing.
  172. X    I know the barricades, and I know the mortar in the wall
  173. X    I recognise the weapons, I use them well.
  174. X
  175. X    This is my mistake, let me make it good,
  176. X    I raised the wall, and I will be the one to knock it down...
  177. X
  178. X- writing password cracking programs gets to you after a bit.
  179. X
  180. X********
  181. X
  182. XSome people have asked me how to generate safe passwords.  This, sadly,
  183. Xhas become a religious issue, and there are now, on USENET, several
  184. Xvociferous "password geeks" who will say "my method is the best", in the
  185. Xsame way that some mathematicians will try to compare so-called "random
  186. Xnumber generating algorithms".  Such statements are pointless.  I'm
  187. Xsorry for adding to the confusion, but I must say that I think they are
  188. Xwrong.
  189. X
  190. XOkay, so I am a security fatalist and a security philosopher, but I am
  191. Xnot going to give and hard and fast answers; rather, I'd like to make
  192. Xsome points and recommendations to the people out there.  Security isn't
  193. Xa tangible thing, it is applied psychology.
  194. X
  195. XThe whole point of a password is to prevent people accessing your
  196. Xsystem, getting into it from outside.  Once someone is inside your
  197. Xsystem, assuming that they have the relevant knowledge of your O/S, it
  198. Xis safest to assume that anyone can get to be 'superuser'.  Your only
  199. Xsecurity once someone is on your system is called "security by
  200. Xobscurity".  If your user has sufficient knowledge, you've "had it".
  201. X
  202. XThe question isn't "How secure can my system be made?".
  203. X
  204. XThe question really should be, "How much do I care, how much can I trust?".
  205. X
  206. XA system can be perfectly secure without any passwords at all, so long
  207. Xas it is in an environment of people who recognise its purpose and
  208. Xdepend on it.  I say this after having had acounts on several 'public'
  209. Xmachines, which could have been taken to bits by any competent Unix
  210. Xperson, but were largely safe - because when someone worked out who did
  211. Xanything nasty, the culprit was ostracised from the community.  There
  212. X_is_ a caveat to this, however.
  213. X
  214. XThe problem is the sort of people who go around the world 'collecting'
  215. Xcomputer accounts and breaking machines, those who have either a
  216. Xchildish mentality or an ulterior motive.
  217. X
  218. XThe former are like the little boys who go around breaking windows and
  219. Xvandalising things 'for kicks'.  They are the ones who see every
  220. Xpassword file as a "NO ENTRY" sign, and therefore, driven by what they
  221. Xthink is anarchy and fun, they break in and smash the place up.  Tell
  222. Xthem that they are behaving like children, and they will behave moreso.
  223. X
  224. XThe latter are driven by personal motives or money.  Their reasons are
  225. Xtoo complex for me to analyse here.
  226. X
  227. XThe 'babyish' hackers need a lesson (which I hope that eventually they
  228. Xlearn) that true anarchy is for the general good, and is best achieved
  229. Xby fiat amongst the community.  USENET is a good example - there is a
  230. Xlot of petty bickering and arguing, but an incredible amount of good
  231. Xcomes out of it.  It is anarchy that the old greek philosophers would
  232. Xhave approved of.
  233. X
  234. XWhat I am trying to say is that, when I say that if someone gets into
  235. Xyour system, you've "had it", you should consider whether there is
  236. Xanything to have "had" in the first place.  There is no point in getting
  237. Xyourself paranoid over security - if you do, you'll lose out.  Don't be
  238. Xtoo paranoid.  Be SENSIBLE instead, and secure your system according to
  239. Xit's needs, and not according to some 'holy bible' of absolute security.
  240. X
  241. XIf someone gets into your system, you find out how they did it, patch
  242. Xthe hole, check for back doors, brush yourself off, and start again.
  243. XIt's not the end of the world.
  244. X
  245. XWhat this statement doesn't address (yet) is the needs of system
  246. Xmanagers who have a REAL need for security - be it corporate data or
  247. Xresearch work - on their system.  As I have said before, most O/S's have
  248. Xgaping holes in them that cannot be entirely filled, and so the crackers
  249. Xmust be stopped on the doorstep.  At the password login.
  250. X
  251. XPeople who say that they have a way of generating safe passwords are
  252. Xmisinformed, IMHO.  Saying that the password "wyufwqpl" is secure is as
  253. Xmeaningful as saying that the number "4" is random.  Password security,
  254. Xlike any other form of computer security, is not absolute, but should
  255. Xbe taken in context.
  256. X
  257. XYou can't say that a certain method will provide secure, random
  258. Xpasswords, because, in defining an algorithm to create these passwords,
  259. Xyou will use only a subset of all the possible passwords that could ever
  260. Xexist.  You have shrunk the 'search space' for the passwords.
  261. X
  262. XSomeone merely has to write a password cracker which will search this
  263. Xsmall subset of passwords, in order to break your system.  Passwords
  264. Xgenerated by any algorithm, human or computer based, are merly
  265. Xpseudo-secure, in the same way that numbers can be pseudo-random.  For
  266. Xillustration of this aspect of password security, read the document
  267. X"Password Security, A Case History" by Morris and Thompson.
  268. X
  269. XThere is an incredibly large set of possible passwords in the world, and
  270. Xthe best approach toward choosing a password is not to try to find a way
  271. Xto generate 'secure' passwords - there are no such things - but rather
  272. Xyou should learn to choose passwords which are not easily searched for.
  273. XPasswords which are out of the 'search space' of most password crackers
  274. Xlike 'Crack'.
  275. X
  276. XRead the Crack documentation.  See what sort of things other programs
  277. Xlike Crack would search for.  Think of some yourself.  I am not going to
  278. Xspecifically mention methods, you should really work something out for
  279. Xyourself.
  280. X
  281. XAt the bottom line, the password "fred" is just as secure (random) as
  282. Xthe password "blurflpox"; the only problem is that "fred" is in a more
  283. Xeasily searched part of the "password space".
  284. X
  285. XBoth of these passwords are more easily found than "Dxk&2+15^N" however.
  286. XNow you must ask yourself if you can cope with remembering "Dxk&2+15^N".
  287. X
  288. X8-)
  289. X
  290. X********
  291. X
  292. XI'd like to thank Chris Samuel & Piercarlo (Peter) Grandi for all their
  293. Xhelp in beta-testing Crack, and in Peter's case especially, for dropping
  294. Xme into the deep end of troff.  Die, you bastard.  8->
  295. X
  296. XI'd also like to thank Chris Myers for giving me an archive site to work
  297. Xfrom (saving me a lot of tedious email) and heaps of suggestions.
  298. X
  299. XSimilarly for Randal Schwartz for his information and Chris Lewis (the
  300. Xpsroff guy) for all his suggestions.
  301. X
  302. XAlso, Brian Tompsett (bct@uk.ac.hull.cs), for pointing me to the now
  303. Xfamous v3.2 bug, and for numerous suggestions and patches, not to
  304. Xmention the enormous amount of debugging information he's sent me about
  305. XCrack v3.3.  To him should go the prize for "Most Vociferous Beta
  306. XTester". 
  307. X
  308. XAnd M.Maclaren, for pointing me towards some changes I could make to toBA64.
  309. X
  310. XAnd finally, to my girlfriend Gilly, for her occasional large doses of
  311. Xsanity.  8-)
  312. X                        - alec
  313. X--
  314. XINET: aem@aber.ac.uk      JANET: aem@uk.ac.aber      BITNET: aem%aber@ukacrl
  315. XUUCP: ...!mcsun!ukc!aber!aem         ARPA: aem%uk.ac.aber@nsfnet-relay.ac.uk
  316. XSNAIL: Alec Muffett, Computer Unit, Llandinam UCW, Aberystwyth, UK, SY23 3DB
  317. END_OF_FILE
  318. if test 13138 -ne `wc -c <'APPENDIX'`; then
  319.     echo shar: \"'APPENDIX'\" unpacked with wrong size!
  320. fi
  321. # end of 'APPENDIX'
  322. fi
  323. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  324.   echo shar: Will not clobber existing file \"'CHANGES'\"
  325. else
  326. echo shar: Extracting \"'CHANGES'\" \(12874 characters\)
  327. sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  328. XChanges file:-
  329. X
  330. X-> Crack 2.7
  331. X
  332. X* Not documented as were expected to be internal only.  Ha bloody ha.
  333. X
  334. X-> Late July 1991
  335. X
  336. X* Posted Crack v2.7 to the net and was immediately swamped with email
  337. X
  338. X* Arranged archiving @ wuarchive.wustl.edu - ~/packages
  339. X
  340. X-> 31 July 1991 v3.1
  341. X
  342. X* First release of Crack 3.1.
  343. X
  344. X* Decided to post future releases with fcrypt() installed.
  345. X
  346. X* Put another 100eps on xform() by using direct addressing of Sn[]
  347. X  arrays in the main loop of xform()
  348. X
  349. X* Oddly enough, using a direct addressing trick instead of (*dp STEP)
  350. X  slows things down on the 5000/200 - I'll leave it as it was.
  351. X
  352. X-> 1 Aug 1991 v3.1b
  353. X
  354. X* Modified Scripts/joinfiles to filter out locked/null account passwords
  355. X  - This fixes a load imbalance on Crack -network.  O/P > crack.inital.
  356. X
  357. X* Removed CRACK_USERNAME as a option - make it mandatory, it's silly to
  358. X  bother turning it off.  Ditto CRACK_USERNAME2
  359. X
  360. X* Modified method of argument parsing in Crack script for more
  361. X  flexibility
  362. X
  363. X* Added a few extra comments to Crack
  364. X
  365. X* Changed Scripts/crack.mf for clarity
  366. X
  367. X* Crack-pwc now uses linked lists for dictionary handling - dicts can be
  368. X  read in until you run out of memory and it crashes.  Fun, eh ?
  369. X
  370. X* Since linked list handling uses pushdown lists, I reversed order of
  371. X  sort in Scripts/makedicts to counteract dictionary reversal - passwords
  372. X  are more common towards the start of the alphabet.  Lazy or what ?
  373. X
  374. X* Removed CRACK_WARN/CRACK_NULLED as options as these jobs are done by
  375. X  Scripts/joinfiles now.  Code left in crack-pwc though, just in case.
  376. X
  377. X* Crack-pwc now creates the output file, not Crack
  378. X
  379. X* Crack-pwc now does checkpointing.  Will need to write recover code
  380. X  soon.
  381. X
  382. X* Renamed output files to "out.*" instead of "crack.*" - also uses the
  383. X  same PID
  384. X
  385. X* Crack-pwc now uses getopt()
  386. X
  387. X* Put -V (verbose) option in : defining CRACK_VERBOSE is still necessary
  388. X  to be able to use this option, however.  It generated a 1Mb file in 90
  389. X  seconds though, so I'm gonna keep it switched off, personally.
  390. X
  391. X* Changed CRACK_NICE to -Nnumber option
  392. X
  393. X* Changed crack-pwc so that input is from stdin _or_ "-Ifilename"
  394. X
  395. X-> August 2 1991 v3.1b
  396. X
  397. X* Paranoia is cracking me up.  in "Crack" when I invoke "-network" with
  398. X  the crack-pwc >& /dev/null < /dev/null - nothing happens.  Well, rather
  399. X  nothing happened.  Until I tried it again this morning.  Now it works.
  400. X  Hmmmmmmm.
  401. X
  402. X* Checkpointing recover code in now spattered all over crack-pwc.c
  403. X
  404. X* The whole idea is that you invoke Crack EXACTLY as before, with the
  405. X  attition of the "-Rpoint.filename.pid" switch.
  406. X
  407. X* If it's not a network Crack, the job will restart where it left off.
  408. X
  409. X* If it IS a network Crack, the whole "rsh" schmeer will take place
  410. X  again, but "crack-pwc" will be left running ONLY on the machine named in
  411. X  the pointfile.  If you need to run it on a different host, change the
  412. X  name of the host in the pointfile. This could cause problems tho.
  413. X
  414. X* Fixed Scripts/Crack.network to parse arguments and allow network.conf
  415. X  to contain per-hostname Crack arguments.
  416. X
  417. X* Fixed Scripts/RCrack to support the above
  418. X
  419. X* Started reworking README in ms macros
  420. X
  421. X-> August 5 1991 v3.1b
  422. X
  423. X* Totally rewritten README
  424. X
  425. X* Doublechecked fcrypt() still works on Sun 4/330 - works fine.
  426. X
  427. X* Tidied fcrypt() configuration symbols into conf.h and reworked some
  428. X  comments in conf.h for readability
  429. X
  430. X-> 7/8 Aug 1991 v3.1b
  431. X
  432. X* *!*!*!*!*!* LOWERCASED ALL OPTION SWITCHES
  433. X
  434. X* Added new -R as distinct from -r in that it recovers with a username
  435. X  check.
  436. X
  437. X* Introduced Sources/crack-port.c with a version of gethostname() which
  438. X  uses uname() on SysV like systems.  Use CRACK_UNAME switch in
  439. X  Sources/conf.h to enable this.
  440. X
  441. X* Edited Scripts/RCrack to put 'rsh' into a variable name for easier
  442. X  access to SysV or SCO ppl who want to change it to 'rcmd'.
  443. X
  444. X* Fixed up the README a bit more
  445. X
  446. X* Redid CRACK_PW_TRUNCATE to be more clever, as CRACK_PW_VERIFY
  447. X
  448. X-> 9 Aug 1991 v3.1c
  449. X
  450. X* Removed library type stuff from Sources/Makefile - Chris Lewis pointed
  451. X  out problems this would generate with portability.
  452. X
  453. X* Batching alternative version of Crack script written in 'sh'
  454. X
  455. X* Crack.sh finished and documented (slightly)
  456. X
  457. X* Fixed remaining bug left from lowercasing switches...  next time I'll
  458. X  be quicker to check my getopt() string
  459. X
  460. X* Did a better MANIFEST file
  461. X
  462. X* Found a bug in Scripts/crack.mf - there was no target for $(DICTSRC) -
  463. X  fixed.  This showed up when 'makekit' dropped the bad_pws.dat file
  464. X
  465. X-> 12 Aug 1991 v3.2a
  466. X
  467. X* Putting a simplified numerics pass into the preprocessor to create an
  468. X  additional dictionary.
  469. X
  470. X* Got a mail message from a guy telling me that I should sort&uniq my
  471. X  dictionaries - evidently he hasn't been reading the shellscripts, just
  472. X  the code.  Ah well.
  473. X
  474. X* Revamped docs for things I'd missed
  475. X
  476. X* Made o/p of pwc in Crack a variable - that way I can select it at the
  477. X  top of the file
  478. X
  479. X* Fixed a bug in GetPoint - didnt always return NULL when it should
  480. X
  481. X* Found a pointing bug in Pass2 - if data HAD changed, program could
  482. X  have walked off the end of the linked list.
  483. X
  484. X* Emptied network.conf for distribution
  485. X
  486. X* Bought the new 'Jam' CD compilation
  487. X
  488. X* Attempted to wrap progs up for testing.
  489. X
  490. X-> Aug 19th 1991 v3.2a
  491. X
  492. X* Got back from Cropredy with a list of things to do.
  493. X
  494. X* Created new way of putting dicts into crack - just drop them into
  495. X  DictSrc and the program should take care of the rest of it.  Saves
  496. X  editing files and with dictionaries.tar.Z now available, it will save
  497. X  a lot of bother for people - they just have to drop them into the
  498. X  directory.  Updated docs accordingly.
  499. X
  500. X* Created APPENDIX file for people who query my methods and sanity.
  501. X
  502. X* added personalisation to conf.h for my purposes only.  Also, according
  503. X  to one guy, his system barfed the comments in conf.h because they
  504. X  started on the same line as a #undef.
  505. X
  506. X* Crack-pp now ignores dictionary lines beginning with '#' - this allows
  507. X  the Klein dictionaries to be dropped straight into the DictSrc
  508. X  directory.
  509. X
  510. X* Crack-pwc now tries a username+reversed username permutation that
  511. X  someone suggested, I've forgotten who and it's buried in 3Mb of email.
  512. X
  513. X* Redid the manifest (again) .
  514. X
  515. X* Modified CRACK_TRAILING to do a leading-digits pass.
  516. X
  517. X* Crack-pwc.c now skips empty dictionaries.
  518. X
  519. X* I found that in using wildcards in Scripts/crack.mf, I created a
  520. X  problem.  The DICTSRC target contined a member DictSrc/* which was
  521. X  always out of date, because it was never made when I called 'make
  522. X  dictstamp' - Make looks for something literally called 'DictSrc/*' and
  523. X  not the individual files.  Hopefully, removing the (blank) dependency
  524. X  for $(DICTSRC) will fix this.  Subtle and annoying.
  525. X
  526. X-> Aug 20th 1991 v3.2a
  527. X
  528. X* Tagged a few extra comments onto APPENDIX
  529. X
  530. X-> Aug 21st 1991 v3.2a
  531. X
  532. X* Cleaned up a bit of the README files. Ready for release.
  533. X
  534. X* Last minute check - found that using 'gcc' as opposed to 'cc' made
  535. X  fcrypt() slow and incompatible with the standard crypt() - this is not
  536. X  nice.
  537. X
  538. X-> Aug 22nd 1991 v3.2a
  539. X
  540. X* First bug reports coming back.  AIX doesnt like fcrypt(), possibly due
  541. X  to putting numbers > 255 in a u_char in fcrypt() - fixed this.
  542. X
  543. X-> Aug 23rd 1991 v3.2a
  544. X
  545. X* Second major bug report in "plaster" - should not assume '.' is in the
  546. X  path, is a security hole.  Fixed.
  547. X
  548. X* Apparently fixing the >8bit bytes does not help fcrypt() on AIX - it
  549. X  still fails.  Bother.
  550. X
  551. X-> Aug 27 1991 v3.2b
  552. X
  553. X* Put newlines in AWK script embedded in Scripts/RCrack - apparently
  554. X  some awks need linebreaks
  555. X
  556. X* Pointfile now contains a datestamp obtained from ctime() - saves on
  557. X  headaches.
  558. X
  559. X* crack-fcrypt.c: removed use of R[] block by finding the ONE place it
  560. X  was referenced and replacing it with a modified reference to L[].
  561. X  This means that the new L[] is the old R[] + L[].  There are no more
  562. X  contiguity problems, so 'gcc' now works, but it is slower than the
  563. X  output of 'cc' on my DECStation.  Caveat Emptor.
  564. X
  565. X* Crack rewritten in 'sh'
  566. X
  567. X* Scripts rewired for greater flexibility
  568. X
  569. X-> 28 Aug 1991 v3.3a
  570. X
  571. X* Fixed bug in init() stuff - a tmpE array was declared with size [32]
  572. X  and not [48] - this was causing problems on a Sun 3, causing coredumps.
  573. X
  574. X* Clarified Endianitis in conf.h - definitely traced to fcrypt problems
  575. X  on RS/6000 and HP's.
  576. X
  577. X* Added Chris Stassens (?) improvements to the load balancing algorithm
  578. X  in Crack.network
  579. X
  580. X* Wired -N switch into crack-pwc to prevent Crack.network working unless
  581. X  CRACK_NETWORK defined.
  582. X
  583. X-> 29 Aug 1991 v3.3a
  584. X
  585. X* Fixed up a few filenames which > 14 chars long.  Probably missed a
  586. X  few.  Hohum.
  587. X
  588. X* Added env variable CRACK_OUT to Crack, as a directory to put output files.
  589. X
  590. X* Spent rest of day playing with Oraperl.
  591. X
  592. X-> 29 Aug 1991 v3.3a
  593. X
  594. X* Fixed up crack-pp dictionary preprocessor to be more flexible about
  595. X  when it generates plurals...  I originally restricted it to lowercase
  596. X  words in order to keep it under control, but it has proved so horribly
  597. X  successful that it needs extending.
  598. X
  599. X* Put "umask 077 in Crack"
  600. X
  601. X* Touched up README.FIRST in anticipation of the next release.
  602. X
  603. X* Touched up README.
  604. X
  605. X-> 3rd Sep 1991 v3.3a
  606. X
  607. X* crack-pwc now unlinks "die" and "point" files on exit
  608. X
  609. X* Scripts/do_join now traps passwords with '*' '!' and SPCs anywhere
  610. X  in the string, and logs them to file.
  611. X
  612. X* Found some people are posting patches to comp.sources.bugs without
  613. X  telling me all about it.  Most annoying, but at least it means that
  614. X  the fixes are going out.  Hohum.  I suppose you must get used to it if
  615. X  you go round casting your pearls before swine...  8-)
  616. X
  617. X-> 4th Sep 1991 v3.3a
  618. X
  619. X* Crack now can run in foreground mode (-f option) :- useful for
  620. X  invocation from other programs.  Unlike the patches which other ppl
  621. X  supply to do this job, Crack 3.3 actually does a bit of sanity
  622. X  checking of arguments (eg: no foreground mode for Crack -network),
  623. X  and it warns of the importance of the out.init.$$ file.
  624. X
  625. X* Crack-pp now does somewhat better pluralisation.  If any linguists
  626. X  dare tell me about the weak points and exceptions, they can go stuff
  627. X  themselves.  8-)
  628. X
  629. X* Crack.network now distributes load on basis of salted lines -
  630. X  splitting salts evenly over the network.  This satisfies some pedants,
  631. X  and to be honest, even I was quite surprised at the way that the load
  632. X  rebalances.
  633. X
  634. X* Changes name of point.<host>.<pid> to pnt.<host>.<pid>
  635. X
  636. X* Put feedback code into crack-pwc
  637. X
  638. X* Created simple feedback script in Scripts directory.
  639. X
  640. X-> 4th Sep 1991 v3.3a
  641. X
  642. X* Tidied up feedback code in crack-pwc.c
  643. X
  644. X* Put all runtime diagnostic files into directory 'Runtime'
  645. X
  646. X* Got rid of the MCB pass - it never showed anything up anyway.  No
  647. X  doubt someone will attack me for this though...
  648. X
  649. X* Inserted feedback-filter code into Crack
  650. X
  651. X* Had lunch in the arts centre with my sister.
  652. X
  653. X* After a few hours fighting with fcrypt(), basically inlining the whole
  654. X  of toBA64(), I measure fcrypt() as 15 times faster than standard.
  655. X  Found a compiler weirdness too - read the bottom of the XForm()
  656. X  function in crack-fcrypt.c
  657. X
  658. X-> 5th Sep 1991 v3.3a
  659. X
  660. X* Fixed a bug in crack-lib.c - Initcap wasn't working properly
  661. X
  662. X* Fixed up feedback mode to lookup guessable and non-guessable
  663. X  passwords, and wired code into do_join instead of independent utility.
  664. X
  665. X* NEW FORMAT NETWORK.CONF - allows specification of different usernames
  666. X  for 'rsh', and ability to specify a copy of Crack OTHER than that you
  667. X  are using.
  668. X
  669. X* Created a slightly duboius Scripts/shadmrg script, to merge
  670. X  /etc/shadow on Sys V systems
  671. X
  672. X* Fixed CRACK_GECOS so that it took in info AFTER a ','
  673. X
  674. X-> 9th Sep 1991 v3.3a
  675. X
  676. X* reinstated MCB pass as reverse forced capitalised
  677. X
  678. X-> 11th Sep 1991
  679. X
  680. X* Installed serries of patches back from bct@hull.cs, lots of minor
  681. X  for protability probs and a new feature - smart rsh-ing.
  682. X
  683. X-> 13th Sep 1991
  684. X
  685. X* Okay, I won't go into detail because its horribly complex, but at
  686. X  least simpler that Brian's solution (grin)...  Crack can do remote
  687. X  processing on machines without NFS by invoking them with the '-f'
  688. X  option (specified in network.conf) and backgrounding the rsh on the
  689. X  server, rather than letting it exit.  Functionally identical but a bit
  690. X  neater.
  691. X
  692. X* Trivial bugfix - crack-pp no longer exits when it finds it cannot read
  693. X  a source dictionary.  It just warns about it.
  694. X
  695. X-> Wed 18th Sep 1991
  696. X
  697. X* Got Gilly to proofread the README file...  tidied it up quite a bit.
  698. X
  699. X* Got some more back off BCT about the state of Crack 3.3c.  There was a
  700. X  fencing error in saltcount and it RCrack needed a sanity check
  701. X  installing to prevent it from rshing to another machine with no data
  702. X  to crack.  Have installed similar trap in Crack.network.  Removed
  703. X  reference to /dev/tty in RCrack's big awk script.
  704. X
  705. X* Found bugs in the pluralisation algorithms, mostly to do with over
  706. X  zealout fprintfs.  Reimplemented more elegantly.
  707. X
  708. X-> 19th Sep 1991
  709. X
  710. X* Added/documented guess2fbk script
  711. X
  712. X-> 20th Sep 1991
  713. X
  714. X* Packaged v3.3 up ready to go.
  715. X
  716. X* Had a great idea.
  717. X
  718. X* Started work on v4.0.
  719. END_OF_FILE
  720. if test 12874 -ne `wc -c <'CHANGES'`; then
  721.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  722. fi
  723. # end of 'CHANGES'
  724. fi
  725. if test -f 'Sources/crack-pwc.c' -a "${1}" != "-c" ; then 
  726.   echo shar: Will not clobber existing file \"'Sources/crack-pwc.c'\"
  727. else
  728. echo shar: Extracting \"'Sources/crack-pwc.c'\" \(21449 characters\)
  729. sed "s/^X//" >'Sources/crack-pwc.c' <<'END_OF_FILE'
  730. X#include "crack.h"
  731. X
  732. X#ifdef hpux    /* You could add your particular unix variant here */
  733. Xchar rcmd[] = "remsh";
  734. X#else
  735. Xchar rcmd[] = "rsh";
  736. X#endif
  737. X
  738. Xchar version[] = "3.3c";    /* version of prog */
  739. Xchar runtime[] = "Runtime";
  740. Xchar feedback_string[] = "!fb!";
  741. X
  742. X/*
  743. X * This program is copyright (c) Alec Muffett 1991 except for certain
  744. X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
  745. X * Sparry and Alec Muffett.  The author(s) disclaims all responsibility or
  746. X * liability with respect to it's usage or its effect upon hardware or
  747. X * computer systems.  This software is in freely redistributable PROVIDED
  748. X * that this notice remains intact.
  749. X */
  750. X
  751. X/*
  752. X * crack-pwc.c - an optimised password cracker. (c) ADE Muffett, July 1991.
  753. X * Totally rewritten from an 'standard' password cracker that had been
  754. X * floating about on ther network. Apart from the entire re-write, to save my
  755. X * sanity, this thing orders passwords to minimise calls to crypt(). Use
  756. X * fcrypt() where you have it.
  757. X */
  758. X
  759. X/* Structure definitions */
  760. X
  761. Xstruct USER_ENTRY
  762. X{
  763. X    int done;            /* bool flag */
  764. X    char *filename;        /* where we got it from */
  765. X    char *passwd_txt;        /* plaintext of password */
  766. X    struct passwd passwd;    /* ...guess... */
  767. X    struct USER_ENTRY *across;    /* line of users with same salt */
  768. X    struct USER_ENTRY *next;    /* next users with different salt */
  769. X};
  770. X
  771. Xstruct DICT_ENTRY
  772. X{
  773. X    char *word;            /* simple linked list */
  774. X    struct DICT_ENTRY *next;
  775. X};
  776. X/* Variable declarations */
  777. X
  778. Xstruct USER_ENTRY *user_root;    /* root of the USER linked list */
  779. X
  780. Xint recover_bool;        /* we are trying to recover from a crash */
  781. Xint verify_recover;        /* we will doublecheck usernames on recovery */
  782. Xint rpid;            /* pid we are recovering */
  783. Xchar rdict[STRINGSIZE];        /* dict we are recovering */
  784. Xchar rusername[STRINGSIZE];    /* username we are recovering */
  785. Xchar rhostname[STRINGSIZE];    /* hostname we are recovering on */
  786. Xint rusercount;            /* count of user we are recovering at;
  787. X                 * strictly, this is the line of the user we
  788. X                 * are recovering */
  789. X
  790. Xint verbose_bool;        /* is verbose switched on ? */
  791. X
  792. Xint pid;            /* pid of parent process */
  793. Xchar opfile[STRINGSIZE];    /* name of output file */
  794. Xchar diefile[STRINGSIZE];    /* name of diefile */
  795. Xchar pointfile[STRINGSIZE];    /* name of pointfile */
  796. Xchar feedbackfile[STRINGSIZE];    /* guess */
  797. Xchar hostname[STRINGSIZE];
  798. X
  799. X/*
  800. X * DIDDY LITTLE USEFUL FUNCTIONS
  801. X */
  802. X
  803. Xvoid
  804. XLog (fmt, a, b, c, d, e, f, g, h, i, j)
  805. X    char *fmt;
  806. X{
  807. X    long t;
  808. X
  809. X    time (&t);
  810. X    printf ("pwc: %-15.15s ", ctime (&t) + 4);
  811. X    printf (fmt, a, b, c, d, e, f, g, h, i, j);
  812. X    fflush (stdout);
  813. X}
  814. X
  815. Xvoid
  816. XCatchTERM ()
  817. X{
  818. X    /* bury magnets */
  819. X    Log ("Caught a SIGTERM! Commiting suicide...\n");
  820. X    /* swallow the rapture */
  821. X    Log ("<argh!>\n");
  822. X    /* let's gather feathers */
  823. X    sync ();
  824. X    /* - don't fall on me */
  825. X    exit (0);
  826. X}
  827. X
  828. Xvoid
  829. XSetPoint (dict, usernumber, username)    /* Sets the pointfile up */
  830. X    char *dict;
  831. X    int usernumber;
  832. X    char *username;
  833. X{
  834. X    FILE *fp;
  835. X    long t;
  836. X
  837. X    if (!(fp = fopen (pointfile, "w")))
  838. X    {
  839. X    perror (pointfile);
  840. X    return;
  841. X    }
  842. X    time (&t);
  843. X#ifdef CRACK_NETWORK
  844. X    fprintf (fp, "%s\n", hostname);
  845. X#endif
  846. X    fprintf (fp, "%d\n", pid);
  847. X    fprintf (fp, "%s\n", dict);
  848. X    fprintf (fp, "%d\n", usernumber);
  849. X    fprintf (fp, "%s\n", username);
  850. X    fprintf (fp, "last pointed: %s", ctime (&t));
  851. X    fclose (fp);
  852. X}
  853. X
  854. Xint                /* returns 0 if OK, -1 if not recovering */
  855. XGetPoint (pf)
  856. X    char *pf;
  857. X{
  858. X    FILE *fp;
  859. X    char buffer[STRINGSIZE];
  860. X
  861. X    if (!(fp = fopen (pf, "r")))
  862. X    {
  863. X    perror (pf);
  864. X    return (-1);
  865. X    }
  866. X#ifdef CRACK_NETWORK
  867. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the hostname */
  868. X    {
  869. X    fprintf (stderr, "get hostname flopped\n");
  870. X    return (-1);
  871. X    }
  872. X    Trim (buffer);
  873. X
  874. X    if (strcmp (buffer, hostname))    /* Not running on original host */
  875. X    {
  876. X    fprintf (stderr, "cmp hostname flopped\n");
  877. X    return (-1);
  878. X    }
  879. X    strcpy (rhostname, buffer);
  880. X#endif
  881. X
  882. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the pid */
  883. X    {
  884. X    fprintf (stderr, "get pid flopped\n");
  885. X    return (-1);
  886. X    }
  887. X    Trim (buffer);
  888. X    rpid = atoi (buffer);
  889. X
  890. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the dictname */
  891. X    {
  892. X    fprintf (stderr, "get dict flopped\n");
  893. X    return (-1);
  894. X    }
  895. X    Trim (buffer);
  896. X    strcpy (rdict, buffer);
  897. X
  898. X    if (!fgets (buffer, STRINGSIZE, fp))
  899. X    {
  900. X    fprintf (stderr, "get usercount flopped\n");
  901. X    return (-1);
  902. X    }
  903. X    Trim (buffer);
  904. X    rusercount = atoi (buffer);    /* Get the usernumber to recover */
  905. X
  906. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the username */
  907. X    {
  908. X    fprintf (stderr, "get username flopped\n");
  909. X    return (-1);
  910. X    }
  911. X    Trim (buffer);
  912. X    strcpy (rusername, buffer);
  913. X
  914. X    fclose (fp);
  915. X    return (0);
  916. X}
  917. X/*
  918. X * STRUCTURE SPECIFIC FUNCTIONS
  919. X */
  920. X
  921. Xchar *
  922. XPWSkip (p)            /* jump the ':' in a pwent */
  923. X    register char *p;
  924. X{
  925. X    while (*p && *p != ':')
  926. X    {
  927. X    p++;
  928. X    }
  929. X    if (*p)
  930. X    {
  931. X    *p++ = '\0';
  932. X    }
  933. X    return (p);
  934. X}
  935. X
  936. Xstruct USER_ENTRY *
  937. XParse (buffer)            /* break up input into a structure */
  938. X    register char *buffer;
  939. X{
  940. X    register char *p;
  941. X    register struct USER_ENTRY *retval;
  942. X
  943. X    retval = (struct USER_ENTRY *) malloc (sizeof (struct USER_ENTRY));
  944. X    retval -> next = retval -> across = NULL;
  945. X    retval -> passwd_txt = NULL;
  946. X    retval -> done = 0;
  947. X    Trim (buffer);
  948. X
  949. X    p = Clone (buffer);
  950. X    retval -> filename = p;
  951. X    p = PWSkip (p);
  952. X    retval -> passwd.pw_name = p;
  953. X    p = PWSkip (p);
  954. X    retval -> passwd.pw_passwd = p;
  955. X    p = PWSkip (p);
  956. X    retval -> passwd.pw_uid = atoi (p);
  957. X    p = PWSkip (p);
  958. X    retval -> passwd.pw_gid = atoi (p);
  959. X    p = PWSkip (p);
  960. X    retval -> passwd.pw_gecos = p;
  961. X    p = PWSkip (p);
  962. X    retval -> passwd.pw_dir = p;
  963. X    p = PWSkip (p);
  964. X    retval -> passwd.pw_shell = p;
  965. X    return (retval);
  966. X}
  967. X/*
  968. X * START OF MODULES
  969. X */
  970. X
  971. Xvoid
  972. XLoadData ()            /* load sorted entries into memory */
  973. X{
  974. X    char *ptr;
  975. X    char salt[2];
  976. X    char buffer[STRINGSIZE];
  977. X    int numlines;
  978. X    int numentries;
  979. X    register struct USER_ENTRY *new_element;
  980. X    register struct USER_ENTRY *current_line;
  981. X
  982. X    numlines = 0;
  983. X    numentries = 0;
  984. X    current_line = NULL;
  985. X    salt[0] = salt[1] = '*';
  986. X
  987. X    while (fgets (buffer, STRINGSIZE, stdin))
  988. X    {
  989. X    if (!*buffer || isspace (*buffer))
  990. X    {
  991. X        continue;
  992. X    }
  993. X    new_element = Parse (buffer);
  994. X
  995. X    ptr = new_element -> passwd.pw_passwd;
  996. X    if (!ptr[0])
  997. X    {
  998. X        Log ("Warning! %s (%s in %s) has a NULL password!\n",
  999. X         new_element -> passwd.pw_name,
  1000. X         new_element -> passwd.pw_shell,
  1001. X         new_element -> filename);
  1002. X        continue;
  1003. X    }
  1004. X    if (strchr (ptr, '*') ||
  1005. X        strchr (ptr, '!') ||
  1006. X        strchr (ptr, ' '))
  1007. X    {
  1008. X        Log ("User %s (in %s) has a locked password:- %s\n",
  1009. X         new_element -> passwd.pw_name,
  1010. X         new_element -> filename,
  1011. X         new_element -> passwd.pw_passwd);
  1012. X        continue;
  1013. X    }
  1014. X#ifdef CRACK_PW_VERIFY
  1015. X    if (strlen (ptr) < 13)
  1016. X    {
  1017. X        Log ("User %s (in %s) has a short crypted password - ignoring.\n",
  1018. X         new_element -> passwd.pw_name,
  1019. X         new_element -> filename);
  1020. X        continue;
  1021. X    }
  1022. X    if (strlen (ptr) > 13)
  1023. X    {
  1024. X        Log ("User %s (in %s) has a long crypted password - truncating.\n",
  1025. X         new_element -> passwd.pw_name,
  1026. X         new_element -> filename);
  1027. X        ptr[13] = '\0';
  1028. X    }
  1029. X#endif                /* CRACK_PW_VERIFY */
  1030. X    numentries++;
  1031. X
  1032. X    if (ptr[0] == salt[0] && ptr[1] == salt[1])
  1033. X    {
  1034. X        new_element -> across = current_line;
  1035. X        current_line = new_element;
  1036. X    } else
  1037. X    {
  1038. X        if (current_line)
  1039. X        {
  1040. X        current_line -> next = user_root;
  1041. X        }
  1042. X        user_root = current_line;
  1043. X        current_line = new_element;
  1044. X        numlines++;
  1045. X        salt[0] = ptr[0];
  1046. X        salt[1] = ptr[1];
  1047. X    }
  1048. X    }
  1049. X
  1050. X    if (current_line)        /* last one tends to hang about */
  1051. X    {
  1052. X    current_line -> next = user_root;
  1053. X    user_root = current_line;
  1054. X    numlines++;
  1055. X    }
  1056. X    Log ("Loaded %d password entries into %d salted lines.\n",
  1057. X     numentries, --numlines);
  1058. X
  1059. X    return;
  1060. X}
  1061. X
  1062. Xvoid
  1063. XPrintGuess (eptr, guess)
  1064. X    register struct USER_ENTRY *eptr;
  1065. X    char *guess;
  1066. X{
  1067. X#ifdef CRACK_PRINTOUT        /* prevents (some) appearances in coredumps */
  1068. X    eptr -> passwd_txt = Clone (guess);    /* essential to FeedBack */
  1069. X#endif
  1070. X
  1071. X    Log ("Guessed %s%s (%s in %s) [%s] %s\n",
  1072. X     (eptr -> passwd.pw_uid ? "" : "ROOT PASSWORD "),
  1073. X     eptr -> passwd.pw_name,
  1074. X     eptr -> passwd.pw_shell,
  1075. X     eptr -> filename,
  1076. X#ifdef CRACK_PRINTOUT
  1077. X     guess,
  1078. X#else
  1079. X     "<not printed>",
  1080. X#endif                /* CRACK_PRINTOUT */
  1081. X#ifdef CRACK_PRINTOUT2
  1082. X     eptr -> passwd.pw_passwd
  1083. X#else
  1084. X     ""
  1085. X#endif                /* CRACK_PRINTOUT2 */
  1086. X    );
  1087. X}
  1088. X/*
  1089. X * PASSWORD CRACKING LOW LEVEL FUNCTIONS
  1090. X */
  1091. X
  1092. Xint
  1093. XTryManyUsers (eptr, guess)    /* returns 0 if all done this line */
  1094. X    register struct USER_ENTRY *eptr;
  1095. X    char *guess;
  1096. X{
  1097. X    register int retval;
  1098. X    char guess_crypted[STRINGSIZE];
  1099. X
  1100. X    if (eptr -> done && !eptr -> across)
  1101. X    {
  1102. X    return (0);
  1103. X    }
  1104. X    strcpy (guess_crypted, crypt (guess, eptr -> passwd.pw_passwd));
  1105. X
  1106. X    retval = 0;
  1107. X
  1108. X    while (eptr)
  1109. X    {
  1110. X#ifdef CRACK_VERBOSE        /* Really want to fill your filestore ? */
  1111. X    if (verbose_bool)
  1112. X    {
  1113. X        Log ("Trying '%s' on %s from line %s\n",
  1114. X         guess,
  1115. X         eptr -> passwd.pw_name,
  1116. X         eptr -> filename);
  1117. X    }
  1118. X#endif
  1119. X    if (!strcmp (guess_crypted, eptr -> passwd.pw_passwd))
  1120. X    {
  1121. X        if (!eptr -> done)    /* haven't printed it before */
  1122. X        {
  1123. X        PrintGuess (eptr, guess);
  1124. X        }
  1125. X        eptr -> done = 1;
  1126. X    }
  1127. X    retval += (!eptr -> done);
  1128. X    eptr = eptr -> across;
  1129. X    }
  1130. X
  1131. X    return (retval);
  1132. X}
  1133. X
  1134. Xint
  1135. XTryOneUser (eptr, guess)    /* returns non-null on guessed user */
  1136. X    register struct USER_ENTRY *eptr;
  1137. X    register char *guess;
  1138. X{
  1139. X    if (!guess || !*guess || eptr -> done)
  1140. X    {
  1141. X    return (0);
  1142. X    }
  1143. X#ifdef CRACK_VERBOSE
  1144. X    if (verbose_bool)
  1145. X    {
  1146. X    Log ("Trying '%s' on %s from %s\n",
  1147. X         guess,
  1148. X         eptr -> passwd.pw_name,
  1149. X         eptr -> filename);
  1150. X    }
  1151. X#endif
  1152. X    if (strcmp (crypt (guess, eptr -> passwd.pw_passwd),
  1153. X        eptr -> passwd.pw_passwd))
  1154. X    {
  1155. X    return (0);
  1156. X    }
  1157. X    eptr -> done = 1;
  1158. X    PrintGuess (eptr, guess);
  1159. X    return (1);
  1160. X}
  1161. X/*
  1162. X * TOP LEVEL CRACKING FUNCTION INTERFACE ROUTINE - SINGLE USER ONLY
  1163. X */
  1164. X
  1165. Xint
  1166. XWordTry (entry_ptr, guess)
  1167. X    register struct USER_ENTRY *entry_ptr;
  1168. X    register char *guess;
  1169. X{
  1170. X    int all_lower;
  1171. X    int all_upper;
  1172. X    register char *ptr;
  1173. X    char guess2[STRINGSIZE];
  1174. X
  1175. X    if (!guess[1])        /* avoid wasting time on initials */
  1176. X    {
  1177. X    return (0);
  1178. X    }
  1179. X    if (TryOneUser (entry_ptr, guess) ||
  1180. X    TryOneUser (entry_ptr, Reverse (guess)))
  1181. X    {
  1182. X    return (1);
  1183. X    }
  1184. X    all_upper = all_lower = 1;
  1185. X    ptr = guess;
  1186. X
  1187. X    for (ptr = guess; *ptr; ptr++)
  1188. X    {
  1189. X    if (islower (*ptr))
  1190. X    {
  1191. X        all_upper = 0;
  1192. X    } else if (isupper (*ptr))
  1193. X    {
  1194. X        all_lower = 0;
  1195. X    }
  1196. X    }
  1197. X
  1198. X    if (!all_lower)
  1199. X    {
  1200. X    strcpy (guess2, Lowercase (guess));
  1201. X    if (TryOneUser (entry_ptr, guess2) ||
  1202. X        TryOneUser (entry_ptr, Reverse (guess2)))
  1203. X    {
  1204. X        return (1);
  1205. X    }
  1206. X    }
  1207. X    if (!all_upper)
  1208. X    {
  1209. X    strcpy (guess2, Uppercase (guess));
  1210. X    if (TryOneUser (entry_ptr, guess2) ||
  1211. X        TryOneUser (entry_ptr, Reverse (guess2)))
  1212. X    {
  1213. X        return (1);
  1214. X    }
  1215. X    }
  1216. X    return (0);
  1217. X}
  1218. X/*
  1219. X * END OF PASSWORD GUESSING LAYERS
  1220. X */
  1221. X
  1222. Xvoid
  1223. XPass1 ()
  1224. X{
  1225. X    int cracked;
  1226. X    struct USER_ENTRY *head;
  1227. X    register char *ptr;
  1228. X    register char *ptr2;
  1229. X    char junk[STRINGSIZE];
  1230. X    register struct USER_ENTRY *this;
  1231. X
  1232. X    Log ("starting pass1 password information\n");
  1233. X
  1234. X    for (head = user_root; head; head = head -> next)
  1235. X    {
  1236. X    for (this = head; this; this = this -> across)
  1237. X    {
  1238. X        /* username */
  1239. X        ptr = this -> passwd.pw_name;
  1240. X        if (WordTry (this, ptr))
  1241. X        {
  1242. X        continue;
  1243. X        }
  1244. X        /* usernameusername */
  1245. X        strcpy (junk, ptr);
  1246. X        strcat (junk, ptr);
  1247. X        if (WordTry (this, junk))
  1248. X        {
  1249. X        continue;
  1250. X        }
  1251. X        /* usernameemanresu */
  1252. X        strcpy (junk, ptr);
  1253. X        strcat (junk, Reverse (ptr));
  1254. X        if (WordTry (this, junk))
  1255. X        {
  1256. X        continue;
  1257. X        }
  1258. X#ifdef CRACK_GECOS
  1259. X        /* Gecos information field */
  1260. X        cracked = 0;
  1261. X        ptr = junk;
  1262. X        strcpy (junk, this -> passwd.pw_gecos);
  1263. X        if (*ptr == '-')    /* never seen this, but... */
  1264. X        {
  1265. X        ptr++;
  1266. X        }
  1267. X        if (ptr2 = (char *) strchr (ptr, ';'))    /* trim off junk */
  1268. X        {
  1269. X        *ptr2 = ' ';
  1270. X        }
  1271. X        if (ptr2 = (char *) strchr (ptr, ','))    /* trim off more junk */
  1272. X        {
  1273. X        *ptr2 = ' ';
  1274. X        }
  1275. X        for (;;)
  1276. X        {
  1277. X        if (ptr2 = (char *) strchr (ptr, ' '))
  1278. X        {
  1279. X            *(ptr2++) = '\0';
  1280. X        }
  1281. X        if (WordTry (this, ptr))
  1282. X        {
  1283. X            cracked++;
  1284. X            break;
  1285. X        }
  1286. X        if (ptr2)
  1287. X        {
  1288. X            ptr = ptr2;
  1289. X            while (*ptr && isspace (*ptr))
  1290. X            {
  1291. X            ptr++;
  1292. X            }
  1293. X        } else
  1294. X        {
  1295. X            break;
  1296. X        }
  1297. X        }
  1298. X
  1299. X        if (cracked)
  1300. X        {
  1301. X        continue;
  1302. X        }
  1303. X#endif                /* CRACK_GECOS */
  1304. X    }
  1305. X    }
  1306. X    return;
  1307. X}
  1308. X
  1309. Xvoid
  1310. XPass2 (dictfile)
  1311. X    char *dictfile;
  1312. X{
  1313. X    FILE *fp;
  1314. X    register struct USER_ENTRY *head;
  1315. X    int dictcount;
  1316. X    struct DICT_ENTRY *dictroot;
  1317. X    register struct DICT_ENTRY *scratch;
  1318. X    int pointuser;
  1319. X    char buffer[STRINGSIZE];
  1320. X
  1321. X    Log ("Starting pass2 on dictionary %s\n", dictfile);
  1322. X
  1323. X    if (!(fp = fopen (dictfile, "r")))
  1324. X    {
  1325. X    perror (dictfile);
  1326. X    return;
  1327. X    }
  1328. X    dictcount = 0;
  1329. X    dictroot = (struct DICT_ENTRY *) 0;
  1330. X
  1331. X    while (fgets (buffer, STRINGSIZE, fp))
  1332. X    {
  1333. X    Trim (buffer);
  1334. X    if (!*buffer)
  1335. X    {
  1336. X        continue;
  1337. X    }
  1338. X    scratch = (struct DICT_ENTRY *) malloc (sizeof (struct DICT_ENTRY));
  1339. X    scratch -> word = Clone (buffer);
  1340. X    scratch -> next = dictroot;
  1341. X    dictroot = scratch;
  1342. X    dictcount++;
  1343. X    }
  1344. X
  1345. X    fclose (fp);
  1346. X
  1347. X    Log ("Loaded %d words from %s\n", dictcount, dictfile);
  1348. X
  1349. X    if (dictcount <= 0)
  1350. X    {
  1351. X    Log ("Oops! Where did I get an empty dictionary from ?\n");
  1352. X    return;
  1353. X    }
  1354. X    head = (struct USER_ENTRY *) 0;    /* See "for" loop below */
  1355. X
  1356. X    if (recover_bool)        /* We are recovering */
  1357. X    {
  1358. X    recover_bool = 0;    /* Switch it off */
  1359. X    head = user_root;    /* Start of the userlist */
  1360. X    while (head && rusercount--)    /* For the recover count */
  1361. X    {
  1362. X        head = head -> next;/* Skip to the next user */
  1363. X    }            /* God this is taking a long time to do */
  1364. X    if (!head)        /* Legs on the ground, feet at the bottom */
  1365. X    {
  1366. X        Log ("Recover: data changed : looking for %s ran off end of list",
  1367. X         rusername);    /* puff, puff, puff, pant pant */
  1368. X        Log ("Exiting...\n");
  1369. X        exit (0);
  1370. X    }
  1371. X    if (verify_recover && strcmp (rusername, head -> passwd.pw_name))
  1372. X    {
  1373. X        Log ("Recover: data changed : looking for %s found %s\n",
  1374. X         rusername, head -> passwd.pw_name);
  1375. X        Log ("Exiting...\n");    /* almost there */
  1376. X        exit (0);
  1377. X    }
  1378. X    }
  1379. X    /* at bloody last */
  1380. X    pointuser = 0;        /* we havent pointed anyone yet */
  1381. X
  1382. X    for (head = head ? head : user_root; head; head = head -> next)
  1383. X    {
  1384. X    SetPoint (dictfile, pointuser++, head -> passwd.pw_name);
  1385. X    for (scratch = dictroot; scratch; scratch = scratch -> next)
  1386. X    {
  1387. X        if (!TryManyUsers (head, scratch -> word))
  1388. X        {
  1389. X        break;
  1390. X        }
  1391. X    }
  1392. X    }
  1393. X
  1394. X    Log ("Freeing memory from pass of %s\n", dictfile);
  1395. X    while (dictroot)
  1396. X    {
  1397. X    free (dictroot -> word);
  1398. X    scratch = dictroot -> next;
  1399. X    free (dictroot);
  1400. X    dictroot = scratch;
  1401. X    }
  1402. X}
  1403. X
  1404. Xvoid
  1405. XFeedBack (unguessed)
  1406. X    int unguessed;
  1407. X{
  1408. X    register FILE *fp;
  1409. X    static char fmt[] = "%s:%s:%s:%s\n";
  1410. X    register struct USER_ENTRY *head;
  1411. X    register struct USER_ENTRY *arm;
  1412. X
  1413. X    Log ("Doing feedback file.\n");
  1414. X
  1415. X    fp = (FILE *) 0;
  1416. X
  1417. X    for (head = user_root; head; head = head -> next)
  1418. X    {
  1419. X    for (arm = head; arm; arm = arm -> across)
  1420. X    {
  1421. X        if (arm -> done)
  1422. X        {
  1423. X        if (!fp)    /* horrible little hack - I love it */
  1424. X        {
  1425. X            if (!(fp = fopen (feedbackfile, "w")))
  1426. X            {
  1427. X            perror (feedbackfile);
  1428. X            return;
  1429. X            }
  1430. X            Log ("Feedback file opened.\n");
  1431. X        }
  1432. X        fprintf (fp, fmt, feedback_string, arm -> passwd.pw_passwd,
  1433. X             "Y", arm -> passwd_txt);
  1434. X        } else
  1435. X        {
  1436. X        if (unguessed)
  1437. X        {
  1438. X            if (!fp)    /* and again !!! heheheheheheh */
  1439. X            {
  1440. X            if (!(fp = fopen (feedbackfile, "w")))
  1441. X            {
  1442. X                perror (feedbackfile);
  1443. X                return;
  1444. X            }
  1445. X            Log ("Feedback file opened.\n");
  1446. X            }
  1447. X            /* I think I'm going slightly warped */
  1448. X            fprintf (fp, fmt, feedback_string, arm -> passwd.pw_passwd,
  1449. X                 "N", "");
  1450. X        }
  1451. X        }
  1452. X
  1453. X    }
  1454. X    }
  1455. X    fclose (fp);
  1456. X    Log ("Done feedback file.\n");
  1457. X    return;
  1458. X}
  1459. X
  1460. Xint
  1461. Xmain (argc, argv)
  1462. X    int argc;
  1463. X    char *argv[];
  1464. X{
  1465. X    int i;
  1466. X    FILE *fp;
  1467. X    char *file;
  1468. X    char *crack_out;
  1469. X    int uerr;
  1470. X    extern int optind;
  1471. X    extern char *optarg;
  1472. X    char rshother[STRINGSIZE];
  1473. X    int foreground_bool = 0;
  1474. X    int rshother_bool = 0;
  1475. X    int feedback_bool = 0;
  1476. X    int network_bool = 0;
  1477. X
  1478. X    uerr = 0;
  1479. X    pid = getpid ();        /* fill this out FIRST THING */
  1480. X
  1481. X#ifdef CRACK_NETWORK
  1482. X    if (gethostname (hostname, STRINGSIZE))    /* and this too ! */
  1483. X    {
  1484. X    perror ("gethostname");
  1485. X    }
  1486. X#endif
  1487. X
  1488. X    if (argc == 1)
  1489. X    {
  1490. X    uerr++;
  1491. X    }
  1492. X    while ((i = getopt (argc, argv, "fFNvU:i:r:R:n:")) != EOF)
  1493. X    {
  1494. X    switch (i)
  1495. X    {
  1496. X    case 'N':
  1497. X#ifndef CRACK_NETWORK
  1498. X        Log ("Called remotely but not compiled with CRACK_NETWORK symbol\n");
  1499. X        Log ("Exiting...\n");
  1500. X        exit (1);
  1501. X#else
  1502. X        network_bool = 1;
  1503. X#endif
  1504. X        break;
  1505. X    case 'U':
  1506. X        strcpy (rshother, optarg);
  1507. X        rshother_bool = 1;
  1508. X        break;
  1509. X    case 'F':
  1510. X        feedback_bool = 1;
  1511. X        break;
  1512. X    case 'f':
  1513. X        foreground_bool = 1;
  1514. X        break;
  1515. X    case 'v':
  1516. X        verbose_bool = 1;
  1517. X        break;
  1518. X    case 'n':
  1519. X        nice (atoi (optarg));
  1520. X        break;
  1521. X    case 'R':
  1522. X        verify_recover = 1;
  1523. X        /* nobreak; */
  1524. X    case 'r':
  1525. X        if (GetPoint (optarg))    /* We are not a recovering machine */
  1526. X        {
  1527. X        exit (0);    /* so, silently die... */
  1528. X        }
  1529. X        recover_bool = 1;
  1530. X        break;
  1531. X    case 'i':
  1532. X        if (!freopen (optarg, "r", stdin))
  1533. X        {
  1534. X        perror (optarg);
  1535. X        exit (1);
  1536. X        }
  1537. X        /*
  1538. X         * If we unlink this file here it effectively hides it, as well
  1539. X         * as preventing the file systems all over the network getting
  1540. X         * gummed up with crud. Only delete a tmp file which matches out
  1541. X         * standard template. Anything else might be a user's own file
  1542. X         * bct@hull.cs
  1543. X         */
  1544. X
  1545. X        if (strcmp (optarg, "/tmp/pw.", 8))
  1546. X        {
  1547. X        unlink (optarg);
  1548. X        }
  1549. X        break;
  1550. X    default:
  1551. X    case '?':
  1552. X        uerr++;
  1553. X        break;
  1554. X    }
  1555. X    }
  1556. X
  1557. X    if (optind >= argc)
  1558. X    {
  1559. X    uerr++;
  1560. X    }
  1561. X    if (uerr)
  1562. X    {
  1563. X    fprintf (stderr,
  1564. X         "Usage: %s [-NFfv] [-ifile] [-nn] [-<R|r>file] [-Uname] dictfile [...]\n",
  1565. X         argv[0]);
  1566. X    exit (1);
  1567. X    }
  1568. X    crack_out = (char *) getenv ("CRACK_OUT");
  1569. X
  1570. X    if (!crack_out)
  1571. X    {
  1572. X    crack_out = ".";
  1573. X    }
  1574. X#ifdef CRACK_NETWORK
  1575. X    sprintf (opfile, "%s/out.%s.%d", crack_out, hostname, pid);
  1576. X    sprintf (diefile, "%s/die.%s.%d", runtime, hostname, pid);
  1577. X    sprintf (pointfile, "%s/pnt.%s.%d", runtime, hostname, pid);
  1578. X    sprintf (feedbackfile, "%s/fbk.%s.%d", runtime, hostname, pid);
  1579. X#else
  1580. X    sprintf (opfile, "%s/out.%d", crack_out, pid);
  1581. X    sprintf (diefile, "%s/die.%d", runtime, pid);
  1582. X    sprintf (pointfile, "%s/pnt.%d", runtime, pid);
  1583. X    sprintf (feedbackfile, "%s/fbk.%d", runtime, pid);
  1584. X#endif                /* CRACK_NETWORK */
  1585. X
  1586. X    if (!foreground_bool)
  1587. X    {
  1588. X    if (!freopen (opfile, "w", stdout))
  1589. X    {
  1590. X        perror ("freopen(stdout)");
  1591. X        exit (1);
  1592. X    }
  1593. X    if (!freopen (opfile, "a", stderr))
  1594. X    {
  1595. X        perror ("freopen(stderr)");
  1596. X        exit (1);
  1597. X    }
  1598. X    }
  1599. X    /*
  1600. X     * If we are given a "-f" flag from across the network we must still make
  1601. X     * a die file so the remote machine can still find the right process to
  1602. X     * kill with a plaster  bct@hull.cs
  1603. X     */
  1604. X
  1605. X    if (network_bool || !foreground_bool)
  1606. X    {
  1607. X    if (!(fp = fopen (diefile, "w")))
  1608. X    {
  1609. X        perror (diefile);
  1610. X        exit (1);
  1611. X    }
  1612. X    fprintf (fp, "#!/bin/sh\n");
  1613. X
  1614. X#ifdef CRACK_NETWORK
  1615. X    /*
  1616. X     * Use the "-n" option on "rsh" to avoid problems of input streams
  1617. X     * attached to remote processes. See man page for rsh bct@hull.cs
  1618. X     */
  1619. X
  1620. X    if (rshother_bool)
  1621. X    {
  1622. X        fprintf (fp, "%s %s -n -l %s kill -TERM %d", rcmd, hostname,
  1623. X             rshother, pid);
  1624. X    } else
  1625. X    {
  1626. X        fprintf (fp, "%s %s -n kill -TERM %d", rcmd, hostname, pid);
  1627. X    }
  1628. X#else
  1629. X    fprintf (fp, "kill -TERM %d", pid);
  1630. X#endif                /* CRACK_NETWORK */
  1631. X    fprintf (fp, " && rm $0\n");
  1632. X    fclose (fp);
  1633. X    chmod (diefile, 0700);
  1634. X    }
  1635. X    Log ("Crack: A Sensible Password Cracker v%s by ADE Muffett, 1991\n",
  1636. X     version);
  1637. X
  1638. X#ifdef CRACK_NETWORK
  1639. X    Log ("We are running on networked machine %s\n", hostname);
  1640. X#endif
  1641. X
  1642. X    if (recover_bool)
  1643. X    {
  1644. X#ifdef CRACK_NETWORK
  1645. X    Log ("We are recovering from a crash on %s, PID %d.\n", rhostname, rpid);
  1646. X#else
  1647. X    Log ("We are recovering PID %d from a crash.\n", rpid);
  1648. X#endif
  1649. X    Log ("From Dictionary %s, User number %d.\n", rdict, rusercount);
  1650. X    Log ("Username must match %s\n", rusername);
  1651. X    }
  1652. X#ifdef FCRYPT
  1653. X    init_des ();
  1654. X#endif
  1655. X
  1656. X    /* Quick, verify that we are sane ! */
  1657. X
  1658. X    if (strcmp (crypt ("fredfred", "fredfred"), "frxWbx4IRuBBA"))
  1659. X    {
  1660. X    Log ("Version of crypt() being used internally is not compatible with standard.\n");
  1661. X    Log ("This could be due to byte ordering problems - see the comments in Sources/conf.h\n");
  1662. X    Log ("If there is another reason for this, edit the source to remove this assertion.\n");
  1663. X    Log ("Terminating...\n");
  1664. X    exit (0);
  1665. X    }
  1666. X    signal (SIGTERM, CatchTERM);
  1667. X
  1668. X    Log ("Loading...\n");
  1669. X
  1670. X    LoadData ();
  1671. X
  1672. X    if (!recover_bool)
  1673. X    {
  1674. X    /* We are starting afresh ! Ah, the birds in May ! */
  1675. X    Pass1 ();
  1676. X#ifdef CRACK_PRINTOUT
  1677. X    if (feedback_bool)
  1678. X    {
  1679. X        FeedBack (0);
  1680. X    }
  1681. X#endif                /* CRACK_PRINTOUT */
  1682. X    } else
  1683. X    {
  1684. X    /* Some spodulous creep pulled our plug... */
  1685. X    while ((optind < argc) && strcmp (argv[optind], rdict))
  1686. X    {
  1687. X        optind++;        /* Fly over dicts that we have done */
  1688. X    }
  1689. X    }
  1690. X
  1691. X    for (i = optind; i < argc; i++)
  1692. X    {
  1693. X    Pass2 (argv[i]);
  1694. X#ifdef CRACK_PRINTOUT
  1695. X    if (feedback_bool)
  1696. X    {
  1697. X        FeedBack (0);
  1698. X    }
  1699. X#endif                /* CRACK_PRINTOUT */
  1700. X    }
  1701. X
  1702. X    Log ("Finished. Tidying up files...\n");
  1703. X    if (network_bool || !foreground_bool)
  1704. X    {
  1705. X    unlink (diefile);
  1706. X    }
  1707. X    unlink (pointfile);
  1708. X
  1709. X#ifdef CRACK_PRINTOUT
  1710. X    if (feedback_bool)
  1711. X    {
  1712. X    FeedBack (1);
  1713. X    }
  1714. X#endif                /* CRACK_PRINTOUT */
  1715. X    Log ("Done.\n");
  1716. X    return (0);
  1717. X}
  1718. END_OF_FILE
  1719. if test 21449 -ne `wc -c <'Sources/crack-pwc.c'`; then
  1720.     echo shar: \"'Sources/crack-pwc.c'\" unpacked with wrong size!
  1721. fi
  1722. # end of 'Sources/crack-pwc.c'
  1723. fi
  1724. echo shar: End of archive 3 \(of 5\).
  1725. cp /dev/null ark3isdone
  1726. MISSING=""
  1727. for I in 1 2 3 4 5 ; do
  1728.     if test ! -f ark${I}isdone ; then
  1729.     MISSING="${MISSING} ${I}"
  1730.     fi
  1731. done
  1732. if test "${MISSING}" = "" ; then
  1733.     echo You have unpacked all 5 archives.
  1734.     rm -f ark[1-9]isdone
  1735. else
  1736.     echo You still need to unpack the following archives:
  1737.     echo "        " ${MISSING}
  1738. fi
  1739. ##  End of shell archive.
  1740. exit 0
  1741. exit 0 # Just in case...
  1742. -- 
  1743. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1744. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1745. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1746. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1747.