Our Blog

hash-cracker – password cracking done effectively

Reading time ~18 min


I wrote a tool to help with cracking of hashes, today I finally decided to blog about it. The idea was to take what I’d learned about common patterns in passwords, and put my experience into practice to make password cracking more efficient on future engagements. Below is a short history of how we got to where we are, as well as some examples of how to use it.

The Indirect Start of Hash-cracker

For the start of hash-cracker we first need to go back to the hassle of my notes_all.txt – this was, explicitly, my text file with a list of commands I used most. These notes for hash-cracking are in the image below:

The contents of notes_all.txt were all migrated to what is now known as the Knowledge Base – aka kb.offsec.nl / https://github.com/crypt0rr/kb. This Hugo based website is built with a CI/CD pipeline via GitHub to CloudFlare Pages where it is hosted as well. Feel free to contribute!

During this note migration, I wondered how could I use the hashcat commands more effectively during engagements.

The opportunity I saw was to improve and eventually create a more efficient way of cracking hashes on regular hardware. Think laptop GPUs and low-level computer GPUs. This does not exclude GPU clusters etc. but is not the main goal.

Basically, I have assumed that the commands as shown in the image above should at least be part of the script, not yet thinking further about other techniques and possibilities. With current knowledge, I would approach this differently in the future, first better figuring out exactly what the requirements are before building.

The Actual Start of Hash-cracker

From, assessments I’ve learnt a lot about common patterns people tend to use when setting a new password. For example;

  • Summer2023!
  • John1970?
  • l3kk3rp@ssw0rd

Most commonly used is a word followed by x amount of numbers and a special character. But also, a technique called leet speak – replacing chars a/@ o/0 i/1 e/3 etc.

Based on this information, I started experimenting with hybrid/combinator attacks. In this form of hash cracking attacks you have one list with words as input and a brute force pattern. This brute force pattern can be placed in front or at the end of the words from the list. With this knowledge I wrote some simple commands into a bash script.

  • -m1000 – hash mode NTLM – list of supported modes
  • nt_hashes – a file containing the hashes that I want to crack (e.g. 4ea072db1483a7df8643772b6b25cb43)
  • -a6 – attack mode used, in this case hybrid
  • ?d?d?d?d?s – the brute force pattern where ?d = 0123456789 ?s = «space»!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`
hashcat -m1000 nt_hashes -a6 wordlist '?d?d?d?d?s'
hashcat -m1000 nt_hashes -a6 wordlist '?d?d?d?d?d?s'
hashcat -m1000 nt_hashes -a6 wordlist '?d?d?d?d?d?d?s'

The example above was my first try, this will work for cracking something like Summer2023!, if Summer is in the wordlist. After using this method for a while, I started looking into more attack modes and options within hashcat. Some examples are:


The idea behind hash-cracker was, and still is, to be able to crack efficiently by putting gathered knowledge on password (re)use into a ‘simple’ script. This was all optimised to run quick, but effective jobs on a laptop with a dedicated GPU (NVIDIA M1200 Mobile at the time). To get an idea about the performance of this GPU, I ran the benchmark within hashcat – it is available over here.

After playing around with hashcat on my CLI and being inefficient about it, I put my gathered knowledge into a simple bash script. The first release was one large file with 222 lines of code (without dependencies / add-ins). When started, it looked like this:

$ ./processor.sh 
Hash-cracker v1.0 by crypt0rr

Checking if requirements are met:
[+] Hashcat is installed
[+] common-substr is executable

0. Exit
1. Default light rules
2. Default heavy rules
3. Brute force
4. Iterate results
5. Plain
6. Hybrid
7. Toggle-case
8. Combinator
9. Prefix suffix (advise: first run steps above)
10. Common substring (advise: first run steps above)
99. Show info about modules
100. Show results in usable format
Please enter number:

With a few options already, I felt quite proud being able to do my first (public) release. Also with this release, I included a bunch of example hashes in three different hashing formats, namely:

  • MD5
  • SHA1
  • NT(LM)

With functions like checking requirements to run the script, light rules to have a go with, and also iterate the things I’ve cracked already. To have a look at the code you can checkout the following commit:

git clone https://github.com/sensepost/hash-cracker
git checkout 92986f16507c232178804525e754c89d778a1030 

With this script, efficiency and more effective cracking on a mobile GPU was more noticeable.


The first version had some improvements in the time between releasing v2.0. The major change for v2.0 was moving everything from the main script and into separate files that would be sourced when called. This has two benefits, first the ability to extend and adapt extra features more easily, secondly someone else could actually find what the ‘processors’ were doing.

With v1.7 the Python2 based Password Analysis and Cracking Kit (PACK) was added as functionality. This was expanded on during the development of v2.x – eventually resulting in two effective options, namely:

  • PACK rulegen
  • PACK mask

As the name implies, rulegen is able to create a new ‘rule’ based on the already cracked passwords. So, it takes the cracked passwords from the current potfile (database with hash:plaintext), and performs an analysis for patterns. A rule is created upon the results and this can be used to perform a rule based attack (wordlist + rule).

The mask function does basically the same, but the output is slightly different. This function will output a set of brute-force patterns based on the already cracked passwords. These brute-force patterns are run as-is.

In October 2021, Apple introduced the Apple Silicon M1 Pro / Max processors for their Pro line of MacBooks. After the first models were delivered, hashcat benchmarks started popping up. During this period, I also ordered a M1 Pro equipped MacBook. Since some binaries in hash-cracker are pre-compiled for x64-based systems it would not work directly.

When I got delivery I started compiling the needed binaries to release a Apple Silicon version of hash-cracker. So, (almost) everything from v2.6 was used as starting point for the first release, namely v2.7 – Apple Silicon Edition.

After this new highlight in the hash-cracker journey, I started implementing more options, more logic and playing with variables for almost everything (instead of hardcoding).


Version 3.0 arrived with some small but welcome additions like multi-wordlist support, re-arranged menu and getting rid of hardware monitoring.

From there I started moving some stuff over to separate, source-able, scripts. Also, with the release of v3.1, it is now possible to choose whether or not you use optimised kernels. The most important use-case for optimised kernels is the fact they are optimised for a specific hash mode instead of a bunch. This makes them a lot quicker, but are limited to a character length of 32. Soifthisisyourpassworditwillnotbecrackedwithoptimisedkernels. By default, optimised kernels are enabled but you can disable them by adding the -n flag when starting hash-cracker.

Below v3.1 with the kernel option build in, nice!

$ ./hash-cracker.sh -n
hash-cracker v3.1 by crypt0rr (https://github.com/crypt0rr)

Checking if requirements are met:
[+] Hashcat is installed
[+] common-substr is executable
[+] Python2 available
[+] expander is executable
[+] Potfile "hash-cracker.pot" present
[-] Optimised kernels disabled

v3.2 – CeWL

For those who don’t know CeWL, this is a Custom Word List Generator. The script scrapes information from the site given to it, you can specify the depth and word length you want to save. This is especially useful during assessments for clients with a website, which company doesn’t have one nowadays?

v3.4 – More Flexibility

The latest version as of (2023-03) is v3.4, which supports some more helpful options but most importantly:

  • Proper handling of creating and deleting temporary files – no more tmp_ files in the root directory
  • Proper cleanup of temporary files when the user stops hash-cracker with CTRL+C
  • Numbers of the available options are now reflected in the script names to make them directly recognizable
  • Parameter handling when the user specifies one or more arguments at CLI
  • Ability to disable both optimised kernel and loopback functionality

Have a look at that help menu:

$ ./hash-cracker.sh -h
Note: flags are optional, by default hash-cracker will run with optimized kernels enabled and perform loopback actions.

Usage: ./hash-cracker [FLAG]

 -l / --no-loopback
   Disable loopback functionality
 -n / --no-limit
   Disable the use of optimized kernels (un-limits password length)
 -m / --module-info
   Display information around modules/options
 -s [hash-name] / --search [hash-name]
   Will search local DB for hash module. E.g. '-s ntlm'

So, with the now released v3.4 the following menu is shown to the user. 19 options, all based on efficiency but able to run for days if you want to.

$ ./hash-cracker.sh 
hash-cracker v3.4 by crypt0rr (https://github.com/crypt0rr)

Mandatory modules:
[+] Hashcat is executable
[+] Potfile "hash-cracker.pot" present

Optional modules:
[+] Common-substr is executable
[+] Python2 is executable
[+] Expander is executable
[+] CeWL is executable

Variable Parameters:
[+] Optimised kernels enabled
[+] Loopback enabled

0. Exit
1. Brute force
2. Light rules
3. Heavy rules
4. Enter specific word/name/company
5. Enter specific word/name/company (brute force)
6. Hybrid
7. Toggle-case
8. Combinator
9. Iterate results
10. Prefix suffix (advise: first run steps above)
11. Common substring (advise: first run steps above)
12. PACK rulegen
13. PACK mask
14. Fingerprint attack
15. Directory of word lists plain and then with OneRuleToRuleThemAll
16. Username iteration (only complete NTDS)
17. Markov-chain passwords generator
18. CeWL wordlist generator
19. Digit remover

Please enter job number: 

v3.5 – Small bump in supported hashtypes

Updated supported hash types, based on hashcat v6.2.6-420-gdc51a1a97

v3.6 – Stacker

The 4th of May is World Password Day – so hash-cracker got a quick update which would help cracking password hashes even more on this special day.

Hashcat released the stacking58 rule, hashcat describes this rule as “This rule file is designed to act as a base for usage in a rule stacking runs.”. So, hash-cracker got a new option ’20’. This option will use the new stacking58 rule and do some magic with other rules resulting in a cool new set of cleartexts for your remaining hashes!

v3.7 – Just before

When asking people on points to improve hash-cracker, having a static configuration file for the hashlist and hashtype have been recurring themes. So, with the release of this blogpost, I’ve also released version 3.7 doing exactly this.

Introducing hash-cracker.conf the location where you can set 4 things, namely:

  • HASHCAT – binary path where you’ve installed hashcat
  • HASHTYPE – mode hashcat will run in (e.g. 1000 (NTLM))
  • HASHLIST – file containing target hashes
  • POTFILE – specify the potfile you want to use / create

The Options, how I use them and how they work

hash-cracker v3.7 currently consists of 20 options. These options can be used in the order as available, or in random order. As you use the script more on different datasets, the smartest options for your hardware will naturally emerge.

How do I use the script itself? What options, what order?

The main datasets I use the script for are analysis of NT hashes extracted from NTDS.dit databases. This type of hash does not use, for example, salting or other techniques to increase the difficulty. When a password is converted to an NT hash then the same input will always produce the same output.

For example the password “Welcome0” will always result in NT: b6adc1c00024a2e4456de1e3d065af41.

I also asked ChatGPT to explain what an NT hash is, below is the explanation I received.

ChatGPT explanation of the NT hash

Normally I always start with option 1, brute-force. This option is going to perform a brute force action on the input with common patterns. A brute force attack involves holding a certain character set against the input in completeness and with random order. An Example of such pattern is “?l?l?l?l?d?d?d?d?d”. Here the ‘?d’ stands for digits 0-9 and ‘?l’ stands for lower-case ‘abcdefghijklmnopqrstuvwxyz’. This pattern will arrive at passwords like ‘Hola12345’ / ‘Boat8492’ / ‘Lolz1337’.

After completing this brute-force (option 1), I usually run option 15 using as input all the word lists provided with hash-cracker. This option checks the word lists and adds variations using a rule. A rule creates variations on the entered passwords. Option 15 uses an improved version of OneRuleToRuleThemAll, called OneRuleToRuleThemStill. This option also provides interesting results when combined with other word lists, for example the list provided by hashmob.net, ‘HashMob Combined Full’ – at the time of writing 15.27GB in size.

Once this first batch is completed, I move on to option 9, iterations. This option grabs the jar file (hash-cracker.jar) and filters the already cracked passwords to a temporary file to perform actions with, for each iteration this action is performed, as at each step new passwords may have been cracked which again can serve as input. The temporary file with already cracked passwords is used as input for a rules-based cracking action. As mentioned earlier, rules create variations on the given input, in this case the passwords in the temporary file.

Option 9 is often followed by options 10 and 11. Two options based on common-substr. Common-substr is a simple tool to extract the most common substrings from an input text and is built for password cracking. Option 10 is based on the ‘Prefix & Suffix Substrings’ module and option 11 concerns ‘All Substrings’.

For cracking longer passwords, or passwords where the user thinks they are clever by pasting the same password in sequence, option 8 was created. I often use this option in conjunction with the provided list ‘ignis-10M.txt’. An example of how this option works, the list (ignis-10M.txt) contains ‘password123’ and ‘password456’, option 8 will create ‘password123password123’ and ‘password123password456’ as candidates. Importantly, option 8 asks for two lists of words as input. The larger the second list (right list), the longer the duration of the option will be. This has to do with the underlying logic of hashcat. So for speed, it may be desirable to choose a larger list as the first list and a smaller list as the second list.

After this action with option 8, I continue with option 6, “hybrid”. Hybrid says it all, a hybrid action is done using two techniques. On the one hand a dictionary, on the other hand brute-force. This option incorporates several patterns that I have classified as ‘common’ in the time I have been cracking passwords. For example, the pattern “Welcome1234!” a word followed by about four digits and an exclamation mark. The word list contains the word ‘Welcome’ and the brute-force pattern invents the rest with it ‘1234!’

Often I end with a few repetitions of options 9, 10 and 11. After this I go through the results and see if any patterns stand out and try to get additional results using the same or other options.

In the end it’s mostly trial and error, you will naturally find a pattern that works well for the datasets and environments you interact with. Every country has its own patterns, every environment has its own patterns.

Statistics for N3rds

But, how do the Apple Silicon M1 and M2 Pro perform against my previous NVIDIA M1200?

Let’s take some commonly used hash types to compare. Note, the M1200 used about 55W from the wall during benchmarking, and the M1 Pro used about 25W.

Comparison M1200/M1Pro/M2Pro


Example Hashes

To start cracking hashes you first need hashes, that’s why hash-cracker comes with multiple sets of example hashes.

There is More! Have You Been Pwned?

‘;–have i been pwned? – probably the most recognised and well known platform collecting data from breaches in all forms and sizes – ran by Troy Hunt. You may have used it to check if your own (personal) email address has leaked? Otherwise, have a go on haveibeenpwned.com.

The dataset that is populated with hashes found in leaks and is available for download through the haveibeenpwned-downloader

Some URLs to Bookmark