Tag Archives: passwords

Hashcat Masks

This article covers an alternative tool for the technique presented in Suggested Rules for Suggested Passwords. It uses Hashcat in place of the open source John the Ripper. Hashcat is free to use, but its source is not available.

Check out the previous article first. You’ll need the four example hash files that it contains. Then return here to run the same brute force using Hashcat.

Define a Custom Charset

We’ll use three of Hashcat’s predefined charsets to build the alphanumeric seed for our guesses. They are lowercase (?l), uppercase (?u), and digits (?d).

We only need one custom charset, which we’ll specify with the -1 option (the option’s long name is --custom-charset1). Make sure to enclose the charset string with single quotes, otherwise your shell may misinterpret the question marks. This example uses the 64-bit hashcat-cli64.app for OS X; the options are identical for Linux or Windows binaries.

-1 '?l?u?d'

Define a Mask

You can create a mask via command-line option. The custom charset is number one, i.e. ?1. (Not to be confused with lowercase ?l in this case.) We wish to build groups of triples. So the first step is to create a mask of three characters based on charset 1, like this:


In fact, that mask will produce guesses of one, two, and three characters in length. We only care about alphanumeric triples, so we’ll use the --pw-min option to specify a minimum password length of 3.

Verify the output with the --stdout option.

$ ./hashcat-cli64.app --stdout -m0 -a 3 -1 '?l?u?d' --pw-min=3 '?1?1?1' | less

Now create a mask for the full format. It should be four groups of alphanumeric triples separated by dashes. Use the ?1 placeholder to reference the custom charset defined in the -1 option.


Verify the mask.

$ ./hashcat-cli64.app --stdout -m0 -a 3 -1 '?l?u?d' --pw-min=15 '?1?1?1-?1?1?1-?1?1?1-?1?1?1' | less

Start Guessing

Use the -m option to select the hashing algorithm. So far we’ve been using type 0, which corresponds to MD5.

$ ./hashcat-cli64.app -m0 -a 3 -1 '?l?u?d' --pw-min=15 safari_md5.txt '?1?1?1-?1?1?1-?1?1?1-?1?1?1'
Initializing hashcat v0.47 by atom with 8 threads and 32mb segment-size...

Added hashes from file safari_md5.txt: 8 (1 salts)

Now try the SHA-256 hash function, which is mode 1400.

$ ./hashcat-cli64.app -m1400 -a 3 -1 '?l?u?d' --pw-min=15 safari_sha256.txt ‘?1?1?1-?1?1?1-?1?1?1-?1?1?1'
Initializing hashcat v0.47 by atom with 8 threads and 32mb segment-size...

Added hashes from file safari_sha256.txt: 8 (1 salts)

Note the difference in cracking speed due to the target hashing method. Specific numbers will vary from system to system, but you’ll probably see the words/sec. drop in half when switching from MD5 to SHA-256. This kind of drop is desirable because it affects the work factor (the amount of effort measured in time and computing resources) required for an attacker to iterate guesses.

If a list of password hashes were stolen, you’d want the hashing algorithm to have a high work factor. There are additional methods like salting and algorithms like PBKDF2 that may also increase the work factor.

The choice of hashing algorithm won’t effectively protect weak passwords, whether they’re short (squ!d), use small character sets (8675309), or longer ones based on common words or phrases (221bBakerStreet). In other words, the best security is to prevent the hashed version of the password from being stolen in the first place.

Suggested Rules for Suggested Passwords

Web sites rely on passwords to authenticate users. It’s a way for users to prove who they claim to be — if you know an account’s password then you (are assumed to) own the account. Sites must protect passwords to prevent attackers from stealing them. Users must create strong passwords to prevent attackers from easily guessing them. The password suggestion feature of Safari 7 helps users do this. (Here are a few more ideas).

This case study demonstrates some of the features of John the Ripper, a password cracking tool. It gives a perspective on the strength of suggested passwords and reinforces why sites must manage passwords securely. The scenario assumes that a hacker has obtained a list of hashed passwords and they wish to target the format of Safari’s suggestions.

Safari suggests passwords that consist of four alphanumeric triples. This produces a 15-character password with 12 characters of entropy (the three dashes are static and predictable). They keyspace is 6212 (26 each of upper- and lower-case letters plus 10 digits), or about 271 if you prefer powers of 2.

With this in mind, let’s explore some of John’s features.

First, open the john.local.conf file and add the following line:

.include "$JOHN/john.ahtk.conf"

Now open the john.ahtk.conf file. Add custom rules from the following examples to this file.

Create a Charset File with an External Filter

John uses charset files when running in incremental mode. The charset file contains all the candidate symbols for a password, including probability measures based on position. John selects symbols based on filters and generates probabilities based on cracked passwords in its john.pot file.

Create a filter that extracts upper- and lower-case letters and numbers. Filters are defined by the filter() function that uses a subset of the C programming language.

void filter()
  int i, c;

  i = 0;
  while (c = word[i++]) {
    if(c < '0' || c > '9') {
      if((c < 'a' || c > 'z') && (c < 'A' || c > 'Z')) {
        word = 0;

Create a charset based on this filter. Your john.pot file influences the quality of the probabilities associated with each symbol. In the following example, the charset is generated from over 3 million plaintext passwords.

$ ./john --make-charset=alphanumeric.chr —external=Filter_Alphanumeric john.pot
Loaded 3190632 plaintexts
Generating charsets... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 DONE
Generating cracking order... DONE
Successfully written charset file: alphanumeric.chr (62 characters)

Define an Incremental Rule

Create a rule called Alphanumeric12 to generate 12-character passwords based on the charset that’s just been created.

File = $JOHN/alphanumeric.chr
MinLen = 12
MaxLen = 12
CharCount = 62

Verify that the rule works by using the--stdout option to print brute force guesses.

$ ./john --stdout --incremental:Alphanumeric12 | less

Define a Transformation Rule

Create a rule that inserts a dash (-) after every three letters. The following rule uses the insert (i) command. The insert command’s syntax is iNX, which the John documentation explains as “insert character X in position N and shift the rest right”.


Positions are 0-based (position 0 is before the first letter). Hence, we’ll insert a dash into positions 3, 7, and 11. Note that john requires a single-character position indicator, which means that position 11 needs a special representation (i.e. i11- would be invalid). John uses A-Z to represent positions 10 and greater, e.g. 11 maps to B.

Test your rule by piping the output of the incremental Alphanumeric12 rule into the AHTK_Safari rule. Your specific guesses will vary, but the output should be four triples separated by dashes.

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --stdout | less

Define a Word Generator with an External Rule

The previous technique that combined an incremental charset and a rule demonstrated some John concepts, but wasn’t the most efficient way to crack this password format.

John supports custom word generation using C functions similar to the filter() used previously. The init() function sets up global variables. The generate() function produces a guess based on the pre-defined word[] array.

The following rule generates four triples separated by dashes.

int alnum[63];
int character[15];
int length, maxlength;
int position;

void init()
  int c;
  int i;

  i = 0;
  alnum[0] = 'a';
  while(i < 26) {
    c = alnum[i++];
    alnum[i] = ++c;
  alnum[26] = 'A';
  while(i < 52) {
    c = alnum[i++];
    alnum[i] = ++c;
  alnum[52] = '0';
  while(i < 62) {
    c = alnum[i++];
    alnum[i] = ++c;
  alnum[62] = 0;

  length = 15;
  maxlength = 15;
  position = length - 1;
  i = 0;

  while(i < length) {
    character[i] = 0;
    word[i] = alnum[character[i]];
  --character[length - 1];
  --word[length - 1];
  word[length] = 0;

  word[3] = '-';
  word[7] = '-';
  word[11] = '-';

void generate()
  while(++character[position] > 61) {
    if(position) {
      character[position] = 0;
      word[position] = alnum[character[position]];
      if(3 == position || 7 == position || 11 == position)
    else {
      word = 0;

  word[position] = alnum[character[position]];
  position = length - 1;

Test your rule with the --stdout option. The output should be identical to the following:

$ ./john --stdout --external=AHTK_IncrementalSafari | less

Try Some Test Cases

Create the following four text files.


Now try the combined incremental/transform rules. Remember that it’s up to the web site to store passwords securely. The following examples demonstrate the relative cracking speed for different hashing algorithms. A real web app should store the hashed value of a password based on at least an hmac or, even better, PBKDF2 (with well-chosen parameters). But that’s out of scope for this discussion.

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --format=raw-sha256 safari_sha256.txt

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --format=raw-sha1 safari_sha1.txt

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --format=raw-md5 safari_md5.txt

To prove the point that the dashes do not increase entropy, the following command runs a brute force against 12-character passwords.

$ ./john --incremental=Alphanumeric12 --format=raw-md5 safari_no_dash_md5.txt

Finally, try each of the example sets against your custom generator.

$ ./john --external=AHTK_IncrementalSafari --format=raw-sha256 safari_sha256.txt 
Loaded 8 password hashes with no different salts (Raw SHA-256 [32/64])

The generator will be slightly faster and may seem more elegant than the piping technique. However, the order of guesses will be different because the charset-based approach creates sequences in a statistical order (based on observed passwords) whereas the custom generator works in lexicographic order (e.g. aaa, aab, aac, …). In practice, the distribution of characters in suggested passwords should be uniform. So, neither approach should be superior. They will both eventually exhaust the keyspace —- but not in any reasonable or feasible time.

That’s all for now. There’s plenty more to talk about regarding password security, let alone other security topics. Security has a keyspace of concepts that I won’t be exhausting any time soon.