Rule-based Attack

Description

Rules are a small language for modifying password candidates. They can change, remove, or add characters and can use conditions to reject candidates. -r works in every attack mode.

Why not stick to regular expressions

Why use a specialized rule language instead of regular expressions? Rules are designed to transform candidate passwords efficiently inside hashcat's candidate-generation pipeline. Regular expressions are useful for describing text patterns, but they are not a drop-in replacement for hashcat's candidate transformations.

Compatibility with other rule engines

hashcat's rule syntax shares many operations with John the Ripper and PasswordsPro, but compatibility is not guaranteed. The same rule letter can have different behavior or argument handling between tools, so check the documentation before reusing a rule file.

Implemented compatible functions

The following operations have corresponding functions in John the Ripper and PasswordsPro. Check each tool's documentation for differences in behavior and arguments before reusing rules.

Name Function Description Example Rule Input Word Output Word Note
Passthrough : No operation, the word is unchanged : p@ssW0rd p@ssW0rd
Lowercase l Lowercase all letters l p@ssW0rd p@ssw0rd
Uppercase u Uppercase all letters u p@ssW0rd P@SSW0RD
Capitalize c Capitalize the first character, lowercase the rest c p@ssW0rd P@ssw0rd
Invert Capitalize C Lowercase the first character, uppercase the rest C p@ssW0rd p@SSW0RD
Toggle Case t Toggle the case of all characters in word t p@ssW0rd P@SSw0RD
Toggle @ TN Toggle the case of characters at position N T3 p@ssW0rd p@sSW0rd *
Reverse r Reverse the entire word r p@ssW0rd dr0Wss@p
Duplicate d Duplicate entire word d p@ssW0rd p@ssW0rdp@ssW0rd
Duplicate N pN Append duplicated word N times p2 p@ssW0rd p@ssW0rdp@ssW0rdp@ssW0rd *
Reflect f Duplicate word reversed f p@ssW0rd p@ssW0rddr0Wss@p
Rotate Left { Rotate the word left { p@ssW0rd @ssW0rdp
Rotate Right } Rotate the word right } p@ssW0rd dp@ssW0r
Append Character $X Append character X to end $1$2 p@ssW0rd p@ssW0rd12
Prepend Character ^X Prepend character X to front ^2^1 p@ssW0rd 12p@ssW0rd
Truncate left [ Delete first character [ p@ssW0rd @ssW0rd
Truncate right ] Delete last character ] p@ssW0rd p@ssW0r
Delete @ N DN Delete character at position N D3 p@ssW0rd p@sW0rd *
Extract range xNM Extract M characters, starting at position N x04 p@ssW0rd p@ss * #
Omit range ONM Delete M characters, starting at position N O12 p@ssW0rd psW0rd *
Insert @ N iNX Insert character X at position N i4! p@ssW0rd p@ss!W0rd *
Overwrite @ N oNX Overwrite character at position N with X o3$ p@ssW0rd p@s$W0rd *
Truncate @ N 'N Truncate word at position N '6 p@ssW0rd p@ssW0 *
Replace sXY Replace all instances of X with Y ss$ p@ssW0rd p@$$W0rd
Purge @X Purge all instances of X @s p@ssW0rd p@W0rd
Duplicate first N zN Duplicate first character N times z2 p@ssW0rd ppp@ssW0rd *
Duplicate last N ZN Duplicate last character N times Z2 p@ssW0rd p@ssW0rddd *
Duplicate all q Duplicate every character q p@ssW0rd pp@@ssssWW00rrdd
Extract memory XNMI Insert substring of length M starting from position N of word saved to memory at position I lMX428 p@ssW0rd p@ssw0rdw0 +
Append memory 4 Append the word saved to memory to current word uMl4 p@ssW0rd p@ssw0rdP@SSW0RD +
Prepend memory 6 Prepend the word saved to memory to current word rMr6 p@ssW0rd dr0Wss@pp@ssW0rd +
Memorize M Memorize current word lMuX084 p@ssW0rd P@SSp@ssw0rdW0RD +
  • * Indicates that N starts at 0. For character positions other than 0-9 use A-Z (A=10)
  • + Indicates that the operation is available with command-line rules (-j or -k).
  • # Changed in oclHashcat v1.37 → v1.38 and hashcat v0.51 → v0.52

Rules used to reject plains

NOTE: Reject rules only work either with hashcat-legacy, or when using “-j” or “-k” with hashcat. They will not work as regular rules (in a rule file) with hashcat.

Name Function Description Example Rule Note
Reject less <N Reject plains if their length is greater than N <G *
Reject greater >N Reject plains if their length is less than N >8 *
Reject equal _N Reject plains of length not equal to N _7 *
Reject contain !X Reject plains which contain char X !z
Reject not contain /X Reject plains which do not contain char X /e
Reject equal first (X Reject plains which do not start with X (h
Reject equal last )X Reject plains which do not end with X )t
Reject equal at =NX Reject plains which do not have char X at position N =1a *
Reject contains %NX Reject plains which contain char X less than N times %2a *
Reject contains Q Reject plains where the memory saved matches current word rMrQ e.g. for palindrome
  • * Indicates that N starts at 0. For character positions other than 0-9 use A-Z (A=10)

Implemented specific functions

The following functions are not available in John the Ripper and/or PasswordsPro:

Name Function Description Example Rule Input Word Output Word Note
Swap front k Swap first two characters k p@ssW0rd @pssW0rd
Swap back K Swap last two characters K p@ssW0rd p@ssW0dr
Swap @ N *NM Swap character at position N with character at position M *34 p@ssW0rd p@sWs0rd *
Bitwise shift left LN Bitwise shift left character @ N L2 p@ssW0rd p@æsW0rd *
Bitwise shift right RN Bitwise shift right character @ N R2 p@ssW0rd p@9sW0rd *
ASCII increment +N Increment character @ N by 1 ascii value +2 p@ssW0rd p@tsW0rd *
ASCII decrement -N Decrement character @ N by 1 ascii value -1 p@ssW0rd p?ssW0rd *
Replace N + 1 .N Replace character @ N with value at @ N plus 1 .1 p@ssW0rd psssW0rd *
Replace N - 1 ,N Replace character @ N with value at @ N minus 1 ,1 p@ssW0rd ppssW0rd *
Duplicate block front yN Duplicate first N characters y2 p@ssW0rd p@p@ssW0rd *
Duplicate block back YN Duplicate last N characters Y2 p@ssW0rd p@ssW0rdrd *
Title E Lower case the whole line, then upper case the first letter and every letter after a space E p@ssW0rd w0rld P@ssw0rd W0rld +
Title w/separator eX Upper case the first letter and the letter after each run of the separator X, lower case every other letter. X keeps its own case e- p@ssW0rd-w0rld P@ssw0rd-W0rld +
Toggle w/Nth separator 3NX Toggle case the letter after the Nth instance of a separator char 30- pass-word pass-Word *
  • * Indicates that N starts at 0. For character positions other than 0-9 use A-Z (A=10)
  • + Only in JtR?
  • # In beta or not yet released

Using hex bytes in rules

You can use '\xNN' syntax to use hex bytes in rules.

$ echo "Penguin" | hashcat -j '$\x64' --stdout
Penguind

This is useful for non-printable ASCII characters, multibyte work, etc.

You may need to use double quotes for the rule with some shells (Windows Command Prompt, etc.)

Writing rules

To write useful rules, first identify the patterns you want to test. This usually means analyzing plaintext passwords to find common patterns. For example, people often append a digit to strengthen a password. This gives us two parameters:

  • We want to append something.
  • The value we want to append is a digit.

If we take a look at the function overview we see that we can append something using the '$' function. So, for example, if we want to add a “1” to our password, we write a rule that looks like this.

$1

To try all numbers 1 - 9, use a Hybrid attack. See that page for details.

Also note:

  • Whitespace is ignored unless it is used as a parameter. This lets you format the rules for readability.
  • To comment out some text, it has to start with a “#” char.

Generating rules

There are two ways to automatically “generate” rules.

Random rules

hashcat can generate random rules for the current session. This can be useful after you have tried all your existing rules on all your dictionaries. There are three configuration parameters:

Generates NUM rules to be applied to each attempt:

--generate-rules=NUM

Specifies the number of functions that should be used (minimum to maximum range):

--generate-rules-func-min=NUM
--generate-rules-func-max=NUM

You can also specify the pool of functions that the rule engine will select from:

--generate-rules-func-sel=[function list]

… such as:

--generate-rules-func-sel=ioTlc

This number can be unlimited but large numbers are not recommended. When used in conjunction with -g, any rule outside of this setting will be ignored.

For example, it could generate “l r”, “l ^f”, and “sa@”. These are all valid rules. However, “l ^f sa@ r $3” would be ignored because it contains 5 functions. Default: min=1 max=4

Saving matched rules

This is useful with the rule generator and for statistical analysis of your rulesets.

To save any rule that generated a matched password use these switches:

--debug-mode=1 --debug-file=matched.rule

This will save the matched rule on every match, so the resulting rule file might contain many duplicate rules.

At high cracking speeds, this may slow the attack slightly. At lower speeds, the impact is likely negligible.

Debugging rules

To verify that a rule does what you want, use the --stdout switch and omit the hashlist.

Here is an example:

Create a small dictionary:

$ echo WORd > word

Generate a simple rule. The “c” rule capitalizes the first letter and lower-cases the rest.

$ echo c > rule

And that's how we see the generated debug output:

$ ./hashcat -r rule --stdout word
Word

This feature also provides a fast password candidate generator. You can feed its output to an external program that reads from stdin.

Character class commands

Character Class Commands were added in 7.0.0, expanding the rule logic and bringing hashcat's behavior more in line with John the Ripper.

Only a limited set of character classes is supported (?l, ?u, ?d, ?h, ?H, ?s).

Syntax is similar to John the Ripper's, using the ~ symbol at the beginning of each command.

Supported on both CPU and GPU:

Rule Description
~s?CY Replace all characters of class C in the word with Y
~@?C Remove all characters of class C from the word
~e?C Upper case the first letter and the letter after each run of characters from class C, lower case every other letter. Characters in C keep their own case

Supported only on CPU:

Rule Description
~!?C Reject the word if it contains any character from class C
~/?C Reject the word unless it contains at least one character from class C
~(?C Reject the word unless its first character is in class C
~)?C Reject the word unless its last character is in class C
~=N?C Reject the word unless the character at position N is in class C
~%N?C Reject the word unless the word contains at least N characters from class C

Separators keep their case, and a run of them counts once

Both eX and ~e?C leave the separator itself alone and upper case the letter after a whole run of separators rather than after each one. A run counts once, so e- on foo–bar gives Foo–Bar rather than upper casing twice, and a separator that is itself a letter keeps its own case:

$ printf 'foo--bar\nfoobar\n' | hashcat --stdout -j e-
Foo--Bar
Foobar

$ printf 'foo--bar\nfoobar\n' | hashcat --stdout -j eo
Foo--bar
FooBar

Under eo the separator is o, so in foobar both of them stay lower case and the b after the run of them is upper cased.

Applies to master. The three rule engines disagreed about this until after 8.0.0. The host engine behind -j and -k preserved separators, while the GPU engines lower cased everything including the separator and upper cased the letter after each separator, so eo on foobar gave FooBar on the host and FoOBar on the GPU. For the letter classes ~e?l, ~e?u, ~e?h and ~e?H the host followed the GPU instead. The optimized engine also skipped a class rule when the word held no character of that class, so ~e?s left foobar unchanged rather than producing Foobar. All three now behave as described above. Results differ from 8.0.0 only where a separator is a letter, since digits, symbols and spaces have no case, and in that optimized-engine case.

Using 'p' (Nth instance of a character) with positional rules

NOTE: rules that use the 'p' character position code work only with the '-j' or '-k' command-line options.

The 'p' character position code (see Github here) memorizes the position of the Nth instance of a character, and makes that position available for use in rules that work with positions within the string. 'p' becomes available automatically when using '%' (reject plains unless they have at least X occurrences of a specific character) and '/' (reject plains that do not contain a specific character).

To operate only on the first instance of a character, use %1s or '/':

$ echo -n 'Odessa77' | hashcat --stdout -j '%1s Dp ip$'
Ode$sa77
$ echo -n 'Odessa77' | hashcat --stdout -j '/s Dp ip$'
Ode$sa77

If you only want to operate on the second instance:

$ echo -n 'Odessa77' | hashcat --stdout -j '%2s Dp ip$'
Odes$a77

… etc. Unlike the 's' rule, which replaces all instances of a character, this allows selection of which instance of a character to replace.

You can also use this functionality to replace one character with multiple characters:

$ echo -n 'p@ssW0rd' | hashcat --stdout -j '%1W DpM ip/ ip\ ip/ ip\'
p@ss\/\/0rd

In the examples below, the '%2s' portion of the rule means “reject plains unless they have at least two 's' characters”. The 'p' then refers to the position of the second 's' character.

Name Function Description Example Rule Input Word Output Word Note
Toggle @ Tp Toggle the case of characters at position p %2s Tp p@s.sW0rd p@s.SW0rd
Delete @ p Dp Deletes character at position p %2s Dp p@s.sW0rd p@s.W0rd
Extract range xpM Extracts M characters, starting at position p %2s xp4 p@s.sW0rd sW0r
Omit range OpM Deletes M characters, starting at position p %2s Op2 p@s.sW0rd p@s.0rd
Insert @ p ipX Inserts character X at position p %2s ip! p@s.sW0rd p@s.!sW0rd
Overwrite @ p opX Overwrites character at position p with X %2s op$ p@s.sW0rd p@s.$W0rd
Truncate @ p 'p Truncate word at position p %2s 'p p@s.sW0rd p@s.
Extract memory XpMI Insert substring of length M starting from position p of word saved to memory at position I %2s lMXp28 p@s.sW0rd p@s.sw0rswd
Swap @ p *pM Swaps character at position p with character at position M %2s *p4 p@s.sW0rd p@s.sW0rd
Bitwise shift left Lp Bitwise shift left character @ p %2s Lp p@s.sW0rd p@s.▒W0rd
Bitwise shift right Rp Bitwise shift right character @ p %2s Rp p@s.sW0rd p@s.9W0rd
ASCII increment +p Increment character @ p by 1 ASCII value %2s +p p@s.sW0rd p@s.tW0rd
ASCII decrement -p Decrement character @ p by 1 ASCII value %2s -p p@s.sW0rd p@s.rW0rd
Replace p + 1 .p Replaces character @ p with value at @ p plus 1 %2s .p p@s.sW0rd p@s.WW0rd
Replace p - 1 ,p Replaces character @ p with value at @ p minus 1 %2s ,p p@s.sW0rd p@s..W0rd

Examples

See rules/ folder in hashcat-legacy or hashcat for examples.

Multi-rules

The release of oclHashcat-plus v0.07 introduced a new feature for rule-based cracking.

Instead of just giving one -r parameter and a file, you can now add as many -r's as you want.

They are not executed in a sequence!

Every rule from each rule file is combined with every rule from the other rule files. This lets you build custom combinations of rules.

$ cat 123.rule
$1
$2
$3

$ cat abc.rule
$a
$b
$c

$ hashcat --stdout -r 123.rule -r abc.rule wordlist
hashcat1a
hashcat2a
hashcat3a
hashcat1b
hashcat2b
hashcat3b
hashcat1c
hashcat2c
hashcat3c

Because the total number of generated rules is the product of all lists, stacking multiple large lists can quickly exceed available memory. But a few well-chosen rules can be stacked to great effect.

Supported by

This attack is currently supported by:

Limitations

With hashcat, both the number of functions in a single rule line and the total number of functions in combined rules are limited to 31.

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