This is a follow-on to the post, Hashcat Tutorial – The basics of cracking passwords with hashcat. If you’re brand new to Hashcat, or if you have problems understanding this post, check out that post to get caught up to speed.
Now that you know the basics of Hashcat, it’s time to increasing efficiency and effectiveness through the Hashcat rule engine. This post will cover rule writing basics and some ways to automate rule writing.
Rule writing basics
The Hashcat rule based attack is probably the most efficient attack against passwords longer than 8 characters, but it can be a bit daunting to try and write your own rules. The reason for this is because it is highly configurable, and there is a lot to learn. You will likely have to reference the rules often, but I’ll provide the cliff notes for a few rules.
Basics and debugging
The first thing we want to do is learn how to test the rules we write. Create a simple dictionary with the word ‘spring’:
echo spring> test.dict
Open up a new file in your favorite text editor. This will be our rules file (I’m naming mine, test.rule). Enter a ‘c’ in the rules file and save the file. The ‘c’ rule will capitalize the first letter of the word and lowercase the rest, so spring should become Spring. We can test the rule by doing this:
hashcat64.exe -r test.rule --stdout dict.txt Spring
Here are a few more basic examples from the rules page:
|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 letter and lower the rest||c||p@ssW0rd||P@ssw0rd|
|Invert Capitalize||C||Lowercase first found 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|
Be aware that with the Capitalize rule, !spring or !SPRING would still be !spring, since capitalizing the first character does nothing to digits or special characters.
|Append Character||$X||Append character X to end||$1||p@ssW0rd||p@ssW0rd1|
|Prepend Character||^X||Prepend character X to front||^1||p@ssW0rd||1p@ssW0rd|
Probably the most useful rules are to append characters to the beginning or end of the word. Consider this rule, which would do title casing on the word, and then append 2019:
The $ appends the characters to the word. The space between the c and the $ is for readability. Whitespace is ignored as long as it is not used as a parameter. If you enter the rule in our test.rule file, save it, and then run it, you will get:
hashcat64.exe -r test.rule --stdout dict.txt Spring2019
Prepending characters to the beginning of the word is a bit different, and may seem strange at first. For example if you want to prepend 123 to the beginning of the word, the rule needs to be:
So you need to reverse the characters. If you add the above rule to the rule file, save it, and run it, you’ll get 123spring. If you wanted to combine this with title casing you would need to be careful. If your rule was ^3^2^1 c, then the output would still be 123spring, since the rule is specifying that the prepension occurs and then the title casing. To get the output of 123Spring, you would need to use the rule c ^3^2^1.
|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|
Duplication is great for cracking passwords where the password policy requires a long length. I’ve found that it is common for people to just double or triple their already weak password. Typically I combine duplication with capitalization and appension/prepension, but I often use different variations. Here are some examples of using double rules on the word ‘spring’:
c d $2$0$1$9 --> SpringSpring2019 d c $2$0$1$9 --> Springspring2019 c $2$0$1$9 d --> Spring2019Spring2019 $2$0$1$9 d c --> Spring2019spring2019
|Replace||sXY||Replace all instances of X with Y||ss$||p@ssW0rd||p@$$W0rd|
You can replace characters using the replacement rule. The leetspeak.rule file that comes with Hashcat has some simple examples, and the Incisive-leetspeak.rule file has much more in-dept examples. A downside of the replacement rule is that it does replace all instances. So the rule ss$ would transform password into pa$$word, however it would miss pa$sword.
There are plenty of other rules that can mangle your wordlist, but the ones that I’ve mentioned so far help crack the bulk of hashes (in my experience).
Putting rules together
The next step is figuring out what we want our rule to do, and it usually involves some sort of pattern. For example, if standard password complexity is required, we can expect a password like thie Spring2019, where the first character is capitalized, followed by multiple lowercase characters, and ending with digits, often something memorable like a year or date. So if we want to test all words in our dictionary for this pattern we would need to capitalize the first character, and then append the year. The rule would look like this:
And when ran, we will get:
But what if we want to check lots of years, and not just 2019? Well, we’d have to write another rule specifying the year we want. And then another, and another. It might look something like this:
# You can comment in hashcat rule files with # # Example: spring --> Spring2019 c $1$9$8$1 c $1$9$8$2 c $1$9$8$3 c $1$9$8$4 c $1$9$8$5 c $2$0$1$5 c $2$0$1$6 c $2$0$1$7 c $2$0$1$8 c $2$0$1$9
But then you realize you want to add a special character at the end, because you remember that people often just add an ! at the end of the password, so you write more rules:
# Example: spring --> Spring2019! c $1$9$8$1$! c $1$9$8$2$! c $1$9$8$3$! c $1$9$8$4$! c $1$9$8$5$! c $2$0$1$5$! c $2$0$1$6$! c $2$0$1$7$! c $2$0$1$8$! c $2$0$1$9$!
This can quickly get out of hand if you think about doing this manually. So you’ll need to find some way to automate it. Before moving on to seeing examples of automated rule generation, here are some other useful rules that I frequently use, as well as adapt to cover more use cases:
# Example: thanksgiving --> thanksgiving1234 $1$2$3$4 $1$q$a$z $z$a$q$1 $!$@$#$$ # Example: thanksgiving --> Thanksgiving1234 c $1$2$3$4 c $1$q$a$z c $z$a$q$1 c $!$@$#$$ # Example: winter --> WinterWinter! c d $! # Example: winter --> Winter!Winter! c $! d # Example: winter --> Winterwinter! d $! c # Example: winter --> Winter!winter! $! d c
Keep in mind that usually I create many variations of the above rules, as well is do similar things with prepending the characters.
Automating rule generation
Scripting rule generation – date_rule.py
An example for the need to script a rule file is when you specifically know what kind of rules you want but it would take too long to manually write each rule. I had an idea to write a rule file that appended dates in various formats to each rule, as well as provide the capability to add characters to the beginning or ending of each word. I wanted to include everything from 00-99, 0101-1231, 010180-12312019, and even 01011980-12312019, but at the same time didn’t want to include numbers that weren’t dates, and also wanted to be able to include some flexibility as well. The result was date_rule.py, and here is a basic demonstration of what it does:
I won’t go into how the code works, but at a high level, it builds a rule file that will append the dates to each word in your wordlist. You can also specify additional appensions/prepensions to precede the word or append after the date.
This is just an example of what you can do with a little creativity and some programming ability. However, if programming is not your thing, that shouldn’t stop you from writing your own rules.
Rule generation – Maskprocessor
The wonderful people at team Hashcat have a tool named maskprocessor that allows you to easily create complicated rule files. Maskprocessor is described here and is available for download here, so download it if you want to follow along.
Maskprocessor can help us write rules that can emulate hybrid mask attacks as well as write rules to be used with a mask attack. Here is an example of how you could use maskprocessor to generate a rule file that will effectively add the masks ?a, ?a?a, and -1 ?s?d ?a?1?1 to each word in a wordlist:
mp64.exe -o test.rule "$?a" mp64.exe -o test.rule "$?a $?a" mp64.exe -o test.rule -1 ?s?d "$?a $?1 $?1"
Maskprocessor appends the output to the file, test_rule.rule. We could now perform a rule based attack that is equivalent to running three different hybrid attacks:
Our new, rule-based attack:
hashcat64.exe -a 0 -m 0 md5_hashes.txt wordlist.txt -r test_rule.rule
The hybrid attacks that are replaced with our rule-based attack:
hashcat64.exe -a 6 -m 0 md5_hashes.txt wordlist.txt ?a hashcat64.exe -a 6 -m 0 md5_hashes.txt wordlist.txt ?a?a hashcat64.exe -a 6 -m 0 md5_hashes.txt wordlist.txt -1 ?s?d ?a?1?1
While creating equivalent attacks is interesting, it doesn’t give us any capability we didn’t have before. However, we gain two very important capabilities from mask processor:
1) We can perform a variant of both types of hybrid attacks (-a 6 and -a 7) at the same time, meaning we can place masks on both sides of the word. For example, let’s say you wanted to add digits (?d) to the start of the word and any character (?a) to the end. Here’s the command that would generate the rule:
mp64.exe -o test1.rule "^?d $?a"
2) We can use masks with other rules. Do you want to make the word title cased as well? Here’s the command that generates the rule file:
mp64.exe -o test1.rule "c ^?d $?a"
Maybe you want to title case the word, double it, then add the digit at the beginning and any character at the end? Here’s the command that generates the rule file:
mp64.exe -o test1.rule "c d ^?d $?a"
The possibilities are endless, but of course, the more rules you generate the longer the attack will take. Here is one of my favorite rule generations (Note: depending on the hash algorithm, may take a very long time):
mp64.exe -o jake.rule "c $?a" mp64.exe -o jake.rule "c $?a $?a" mp64.exe -o jake.rule -1 ?s?d "c $?a $?1 $?1" mp64.exe -o jake.rule "c $?d $?d $?d" mp64.exe -o jake.rule "c $?d $?d $?d $?d" mp64.exe -o jake.rule "c $?d $?d $?d $?d $?d" mp64.exe -o jake.rule "c $?d $?d $?d $?d $?d $?d" mp64.exe -o jake.rule "c $?d $?d $?d $?d $?s" mp64.exe -o jake.rule -1 ?s?d "c ^?1" mp64.exe -o jake.rule -1 ?s?d "c ^?1 $?a" mp64.exe -o jake.rule -1 ?s?d "c $?1 $?d $?d $?1" mp64.exe -o jake.rule -1 ?s?d "c $?1 $?d $?d $?d $?d"
This tutorial dug a bit deeper on more effective ways to use Hashcat to recover passwords through rule-writing, but there is still plenty more to learn. Still, you are only limited by your creativity. In a (eventual) follow on post I’ll cover other methods, as well as helpful tools that are available to analyze existing password lists to better optimize attacks.