Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 25 Oct 2010 17:14:55 -0400
From: Brad Tilley <brad@...ystems.com>
To: john-users@...ts.openwall.com
Subject: Re: Solution to this 'l33t' rules problem?

Charles Weir wrote:
> This is a really interesting problem since it's certainly a needed
> attack type to target more advanced passwords. As Brad pointed out,
> the posted suggestion by Solar and Rich to generate replacement rules
> can get really nasty when multiple replace types are implemented at
> the same time, such as 'p@...ord'.  I spent a little bit of time
> trying to write a script to auto-generate a JtR config file that would
> contain those thousands, (if not more), of potential replacement rules
> but I eventually ended up dropping that approach and instead decided
> to make use of JtR's -stdin option.
> 
> On a side note, JtR's -stdin option is one of the main reasons I use
> John. If you can think of a way to generate guesses, even if JtR's
> built in mangling rules doesn't support it, you can always write your
> own program/script to generate the guesses and still use JtR on the
> back-end to handle all of the hashing.
> 
> To that end I wrote the program 'noobify', which is available at the
> following link:
> 
> http://sites.google.com/site/reusablesec/Home/password-cracking-tools/noobify
> 
> Yes the name is a play on l33tify ;)
> 
> I tried to make it as customizable as possible. Below is an
> explanation of a couple of the design choices:
> 
> 1) As the name implies, it will apply every possible replacement rule
> to an input word and then output it for JtR to hash. Aka the word
> 'noobify' could generate n0obify, n00bify, n00b1fy, n0ob1fy, no0bify,
> no0b1fy, noob1fy ...
> 
> 2) It reads in the replacements to use from a tab separated text file,
> (the default file is replacements.txt). This allows the user to
> specify the specific replacements they want to use, vs hard-coding
> them in. For example, you can also do things like uppercase vowels if
> you want by replacing 'a' with 'A', etc. This also allows the user to
> have multiple replacement profiles for use in different cracking
> sessions.
> 
> 3) It replaces substrings instead of characters. This allows for
> multi-character replacements. The most common 'l33t' example would be
> replacing 'f' with 'ph', but it actually opens up a bunch of other
> options as well. For example you can replace '2009' with '2010', or
> 'monday' with 'tuesday'. The replacements do not have to be the same
> size.
> 
> 4) Currently it works a lot like middlechild,
> http://sites.google.com/site/reusablesec/Home/password-cracking-tools/middle-child
> in that it will take input from stdin, and then output it to stdout.
> Probably the most common use of it would be:
> 
> cat <input_dictionary> | ./noobify | ./john -stdin -format=<hashtype>
> <target_hashes>
> 
> 5) Currently it doesn't apply any other mangling rules. If you want to
> apply additional mangling rules you do have a couple of different
> options available to you. The first is to use noobify to generate a
> custom input dictionary instead of piping the output directly into
> John. Then you can use that input dictionary with all of your existing
> JtR mangling rules. The second option is to chain the output into a
> second mangling program like middlechild. For example, the below
> command would also capitalize the first letter and append two digits
> followed by one special character:
> 
> cat <input_dictionary> | ./noobify | ./middlechild -capFirst -append
> D2S1 | ./john -stdin -format=<hashtype> <target_hashes>
> 
> The advantage of this approach is that it works for much larger input
> dictionaries, since you don't have to save the mangled results to
> file. The downside though is that it applies EVERY mangling rule to
> each word before moving on to the next one. When you use John's rules
> you can optimize it a lot more to try high probability rules first,
> which will usually result in you cracking passwords much sooner in
> your cracking session.
> 
> 6) I practice "agile development", which is a nicer way of saying that
> I try to get a proof of concept working before I focus on making it
> 'good'. Currently there's a lot of inefficiencies in the code that
> make it run fairly slow compared to most other mangling rules, (the
> biggest probably being in how I currently identify replacements in the
> actual word). I should be able to fix some of them fairly soon, but
> even in it's current state, at least you can make guesses which were
> difficult to generate beforehand. Also as stated above, you can always
> save the results to file, making the running time of this tool only a
> one time cost.
> 
> 7) I just realized I forgot to test it, but theoretically the tool
> supports deletions as well, (in the replacement file just have the
> value you want to delete followed by a tab and then a return). This
> way you can do things like remove spaces and punctuation from a
> passphrase input dictionary. If it crashes horribly when you try to do
> this I should have a fix soon ;)
> 
> 8) Yes the code is C++ so you will have to compile it. I realize I
> should have written it as a script to make it easier to use, but I
> like writing in C++. The code is GPL'd so feel free to modify it.
> 
> 9) The default replacement file I included is just a proof of concept.
> Aka I got tired after entering the different replacements in for
> 'january', aka january->february, etc, so I didn't do any of the other
> months ;)
> 
> 10) As an addendum to the previous point, be careful when you a
> copying and pasting replacement rules, since many editors will paste
> spaces instead of tabs.
> 
> As always, if you have any questions/comments/suggestions, please let me know.
> 
> Matt Weir
> http://reusablesec.blogspot.com

That's interesting Matt. I hard-coded a Cartesian product solution using
nested for loops. It's fast, but it does not scale as well as your
mangleGuess function would. Here's an example with 2 char passwords...
nest one more level for each additional char:

-------------
std::string one = "nN";
std::string two = "oO0@";

std::string attempt;

std::string::const_iterator it1_end (one.end()), it2_end (two.end());
	
for ( it1 = one.begin(); it1 != it1_end; ++it1 )
{	
	attempt.push_back(*it1);
		
	for ( it2 = two.begin(); it2 != it2_end; ++it2 )
	{	
		attempt.push_back(*it2);	
		std::cout << attempt;					
		attempt.resize(1);
	}
	attempt.clear();	
}
-------------

I'm guessing this would work with JTR's stdin option. I'll try it.

Brad

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.