Mask Attack

Description

This attack tries combinations from a given keyspace, like a Brute-force attack, but allows more specific constraints.

Advantage over Brute-Force

The aim is to reduce the password candidate keyspace and make the attack more efficient.

Here is a single example. We want to crack the password: Julia1984

In a traditional brute-force attack, we need a charset containing all uppercase letters, all lowercase letters and all digits (also known as “mixalpha-numeric”). The password length is 9, so we have to try 62^9 (13.537.086.546.263.552) combinations. At a cracking rate of 100M/s, this takes more than 4 years to complete.

A mask attack can use common patterns in how people choose passwords. The password above follows a common pattern: a name with a year appended. We can configure the attack to try uppercase letters only in the first position. An uppercase letter only in the second or third position is uncommon. This reduces the keyspace to 52*26*26*26*26*10*10*10*10 (237.627.520.000) combinations. At the same cracking rate of 100M/s, this takes just 40 minutes to complete.

Disadvantage compared to Brute-Force

There is no inherent disadvantage: a mask can describe the same keyspace as an unrestricted brute-force attack, or a smaller one when you have useful information about the password. A smaller keyspace can finish sooner, but it may miss the password if your assumptions are wrong.

Masks

We need to configure a placeholder for each position in the generated password candidates. If the password has a length of 8, our mask must consist of 8 placeholders.

  • A mask is a simple string that configures the keyspace of the password candidate engine using placeholders.
  • A placeholder can be either a custom charset variable, a built-in charset variable or a static letter.
  • A variable is indicated by a question mark followed by a built-in charset name (l, u, d, s, a, h, H or b) or a custom charset number (1 through 8).
  • A static letter is not indicated by a letter. An exception is if we want the static letter ? itself, which must be written as ??.

Output

Optimized due its partially reverse algorithms, password candidates are generated in the following order:

aaaaaaaa
aaaabaaa
aaaacaaa
.
.
.
aaaaxzzz
aaaayzzz
aaaazzzz
baaaaaaa
baaabaaa
baaacaaa
.
.
.
baaaxzzz
baaayzzz
baaazzzz
.
.
.
zzzzzzzz

NOTE: The first four letters change first and most often. The exact number can vary, especially in a smaller keyspace, but remains fixed until the keyspace has been scanned completely.

Built-in charsets

  • ?l = abcdefghijklmnopqrstuvwxyz
  • ?u = ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • ?d = 0123456789
  • ?h = 0123456789abcdef
  • ?H = 0123456789ABCDEF
  • ?s = <<space>>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
  • ?a = ?l?u?d?s
  • ?b = 0x00 - 0xff

Custom charsets

Current hashcat versions provide eight command-line options for defining custom charsets. Versions before 7.0.0 provided four.

--custom-charset1=CS
--custom-charset2=CS
--custom-charset3=CS
--custom-charset4=CS
--custom-charset5=CS
--custom-charset6=CS
--custom-charset7=CS
--custom-charset8=CS

These options have the shortcuts -1 through -8. You can specify the characters directly on the command line or use a hashcat charset file (a plain-text .hcchr file). See examples below:

Examples

The following commands all define the same custom charset containing the characters “abcdefghijklmnopqrstuvwxyz0123456789” (also known as “lalpha-numeric”):

-1 abcdefghijklmnopqrstuvwxyz0123456789
-1 abcdefghijklmnopqrstuvwxyz?d
-1 ?l0123456789
-1 ?l?d
-1 loweralpha_numeric.hcchr # file that contains all digits + chars (abcdefghijklmnopqrstuvwxyz0123456789)

The following command defines a charset containing the characters “0123456789abcdef”:

-1 ?dabcdef

The following command defines a printable 7-bit ASCII charset (aka “mixalpha-numeric-all-space”):

-1 ?l?d?s?u

The following command sets the first custom charset (-1) to Russian language-specific characters:

-1 charsets/special/Russian/ru_ISO-8859-5-special.hcchr

Default mask

If -a 3 is requested without specifying a mask, the following default mask is used:

?1?2?2?2?2?2?2?3?3?3?3?d?d?d?d

… where the custom character sets are:

1 - ?l?d?u (lowercase, digits, and uppercase)
2 - ?l?d (lowercase and digits)
3 - ?l?d*!$@_ (lowercase, digits, and five selected special characters)

This mask is also available as a mask file in the ./masks/ directory, as hashcat-default.hcmask.

Example

The following commands create these password candidates:

command: -a 3 ?l?l?l?l?l?l?l?l
keyspace: aaaaaaaa - zzzzzzzz
command: -a 3 -1 ?l?d ?1?1?1?1?1
keyspace: aaaaa - 99999
command: -a 3 password?d
keyspace: password0 - password9
command: -a 3 -1 ?l?u ?1?l?l?l?l?l19?d?d
keyspace: aaaaaa1900 - Zzzzzz1999
command: -a 3 -1 ?dabcdef -2 ?l?u ?1?1?2?2?2?2?2
keyspace: 00aaaaa - ffZZZZZ
command: -a 3 -1 efghijklmnop ?1?1?1
keyspace: eee - ppp

Password length increment

A mask attack is always specific to a target password length. For example, if we use the mask ?l?l?l?l?l?l?l?l we can only crack a password of length 8, and if the target password is length 7, this mask will not find it. That's why we have to repeat the attack several times, each time with one placeholder added to the mask:

?l
?l?l
?l?l?l
?l?l?l?l
?l?l?l?l?l
?l?l?l?l?l?l
?l?l?l?l?l?l?l
?l?l?l?l?l?l?l?l

To automate this, use the --increment flag. It uses the first placeholder, then the first two, then the first three, and so on. You can customize the starting and ending lengths with the --increment-min and --increment-max flags.

Note: the length of the mask itself is also a limiting factor for hashcat. Masks will not increment beyond their own length. For example, if a mask is only of length 4, --increment won't increment beyond length 4, --increment-min of 5 would have no effect, etc.

hashcat charset files

hashcat charset files (file extension: .hcchr) let you reuse charsets, define custom charsets and use the language-specific charsets shipped with hashcat.

These files can be used with the --custom-charsetN= (or -1, -2, -3 and -4) parameter. Instead of providing the whole charset on the command line, specify the path to a .hcchr file:

-1 charsets/standard/German/de_cp1252.hcchr

Create .hcchr files with language-specific file encodings (e.g. cp1252, ISO-8859-15). For examples of content and encoding of .hcchr files, see the examples shipped with hashcat (e.g. [HASHCATROOT]/charsets/standard/Italian/).

Hint: use iconv or similar tools to convert files to a language-specific encoding, for instance if they were created as UTF-8 files.

hashcat mask files

hashcat mask files (file extension: .hcmask) contain masks (e.g. ?1?1?1?1?d?d) and optional custom charsets, one set per line. These plain text files let you store predefined masks in one or more files, such as separate files for different password policies. You can sort the lines by increasing runtime or likelihood of a match*.

The general format of 1 single line in the .hcmask file is as follows:

[?1,][?2,][?3,][?4,][?5,][?6,][?7,][?8,]mask

where the placeholders are as follows:

  • [?1] custom charset 1 (--custom-charset1 or -1) is set to this value (optional)
  • [?2] custom charset 2 (--custom-charset2 or -2) is set to this value (optional)
  • [?3] custom charset 3 (--custom-charset3 or -3) is set to this value (optional)
  • [?4] custom charset 4 (--custom-charset4 or -4) is set to this value (optional)
  • [?5] custom charset 5 (--custom-charset5 or -5) is set to this value (optional)
  • [?6] custom charset 6 (--custom-charset6 or -6) is set to this value (optional)
  • [?7] custom charset 7 (--custom-charset7 or -7) is set to this value (optional)
  • [?8] custom charset 8 (--custom-charset8 or -8) is set to this value (optional)
  • [mask] the mask, which may use any custom charset defined on that line, any built-in charset (?l, ?u, ?d, ?h, ?H, ?s, ?a, ?b), or literal characters (example: pass?1?d?d?2?l?l)

* see the PACK program and some example hcmask files shipped by hashcat (in the masks/ folder).


You supply the .hcmask file just where you would normally place the single mask on the command line, like so:

-a 3 hash.txt mask_file.hcmask


Other less-important syntax available in .hcmask files:

  • with # you can comment a line (it won't be used), with \# you can use a # at the beginning of the line (either within the custom charsets or, if no custom charset is used, within the mask)
  • \, means that the comma should be used literally (not a field separator)
  • ?? within the mask or custom charsets means that the question mark should be used as a literal character (otherwise if only a single question mark was used it would be interpreted as the beginning of a reference to a custom charset or built-in charset)


Notes:

  • .hcmask files can be used with the -i (increment) parameter in brute-force mode.
  • A mask cannot reference a custom charset unless that charset is defined in the same line of the hcmask file.
  • If [?2] is not needed, omit it and the comma after [?2]. See the examples below.

Example

The following .hcmask file contains some valid example lines which show how to use this feature:

?d?l,test?1?1?1
abcdef,0123,ABC,789,?3?3?3?1?1?1?1?2?2?4?4?4?4
company?d?d?d?d?d
?l?l?l?l?d?d?d?d?d?d
?u?l,?s?d,?1?a?a?a?a?2

Note: also see FAQ: What is a hashcat mask file?

Charsets in hex

This can be done by some of the hashcat tools using the “--hex-charset” flag.

Using a mask together with a wordlist

A mask does not have to stand on its own. If you want a real word in the candidate and a mask around it, that is the Hybrid attack:

$ hashcat -a 12 -m 0 hash.txt ?d?d?w?d?d example.dict

?w marks the place the word from the wordlist goes, and the rest of the mask works exactly as it does on this page. -a 6 and -a 7 are the older, narrower forms that only put the mask after or before the word.

Using a mask with a trained grammar

A mask defines which characters are possible at each position. What it cannot capture is whether any of the strings it spells was ever chosen by a person. The PCFG attack can hold a trained grammar to the same mask, so you keep the shape you are sure of and get the candidates inside that shape in the order real passwords occur. It is -a 4 with a mask= setting, and the syntax is the one on this page, read by the same parser:

$ hashcat -m 0 -a 4 example0.hash mask=?u?l?l?l?l?d?d?d

You can see the difference without cracking anything. -a 3 orders a mask with Markov statistics by default, which works one position at a time, so ?a?a?a opens like this:

$ hashcat -a 3 --stdout ?a?a?a | head
sar
mar
1ar
car
bar
aar
0ar
par
lar
jar

The same three positions under -a 4 open with passwords:

$ hashcat -a 4 --stdout mask=?a?a?a | head
123
abc
asd
qwe
may
lol
max
101
007
666

Markov statistics describe which characters are common at each position. The grammar describes which whole passwords are common. That is why 123 and qwe appear first instead of a plausible-looking string nobody ever picked. On a mask this short, the count barely changes: 603,812 candidates against 857,375. The main benefit is the order.

The gain in size arrives with longer masks, because the grammar rules shapes out before the run starts rather than after each candidate. On the ruleset hashcat ships, ?u?l?l?l?l?d?d?d leaves 13 of the grammar's 23,159 shapes:

  • ?u?l?l?l?l?d?d?d is 296,958,668 candidates under -a 4, against 11,881,376,000 for the same mask under -a 3. 40 times smaller.
  • ?u?l?l?l?l?l?l?d?d?d?d?s is 62,006,418,684, against 2,650,497,358,080,000. Roughly 42,700 times smaller.

So the looser the mask, the more there is to rule out. That is the opposite of -a 3, which only rewards you for guessing tightly.

The grammar applies the mask before generating finished candidates. A literal anywhere in the mask constrains which words can surround it. A known fragment is therefore useful even in the middle of a password. The PCFG page shows an example.

There are two constraints to consider. A mask fixes the length, so pwmin and pwmax are taken from it. A length that contradicts the mask is rejected. A masked run also has no OMEN escape. The escape generates guesses one character at a time and leaves no terminals for the mask to filter. hashcat therefore drops it and reports this at startup. On a ruleset trained at the default coverage, the escape carries about 40% of the probability mass. Run the mask and the escape as two attacks if you want both.

Options -i and --increment are rejected under -a 4, because they belong to a mask and the positional argument there is a ruleset. The full reference is docs/hashcat-pcfg.md in the hashcat source.

Except where otherwise noted, content on this wiki is licensed under the following license: Public Domain