Hashcat Brute-Force with Mask Attacks

LinuxBeginner
Practice Now

Introduction

Hashcat is a world-renowned password recovery tool, capable of cracking a wide variety of hashes at incredible speeds. While dictionary attacks are common, they are only effective if the password exists in a given wordlist. A pure brute-force attack, which tries every possible character combination, is often too slow to be practical.

This is where the mask attack comes in. A mask attack is a highly efficient form of brute-force attack that is used when you have some knowledge about the password's structure. For example, you might know the password's length, or that it starts with a capital letter and ends with a number.

In this lab, you will learn the fundamentals of performing a mask attack with Hashcat. You will start by understanding the concept, learn how to use character sets to build masks, and apply this knowledge to crack password hashes with known patterns.

Understand the concept of a mask attack (-a 3)

In this step, you will learn the basic concept of a mask attack in Hashcat. The mask attack mode is specified using the -a 3 option. This mode tells Hashcat to generate password candidates based on a pattern, or "mask," that you define.

This is different from a dictionary attack (-a 0), which uses a pre-made list of words. A mask attack creates its own candidates on the fly.

Let's see how a mask generates candidates. We can use the --stdout option to print the generated passwords to the screen instead of trying to crack a hash. We'll use ?d as a simple placeholder for a digit (0-9).

Run the following command to generate all possible 3-digit numbers:

hashcat -a 3 ?d?d?d --stdout

Hashcat will generate all possible 3-digit combinations. Note that the output order may appear random due to Hashcat's optimization algorithms, but it will generate all combinations from 000 through 999.

...
476
576
876
976
...

This demonstrates the core idea: the mask ?d?d?d acts as a template, and Hashcat systematically fills it in with all possible combinations from the specified character set.

Learn the built-in character sets (?l, ?u, ?d, ?s)

In this step, you will learn about the fundamental building blocks of masks: built-in character sets. These are placeholders that represent a specific group of characters.

Hashcat provides several convenient built-in character sets:

Placeholder Character Set Description
?l abcdefghijklmnopqrstuvwxyz All lowercase letters
?u ABCDEFGHIJKLMNOPQRSTUVWXYZ All uppercase letters
?d 0123456789 All digits
?s !"#$%&'()*+,-./:;<=>?@[\]^_{}~ All special characters (symbols)
?a ?l?u?d?s All possible characters

You can combine these placeholders to create complex masks. The length of the mask directly determines the length of the generated password candidates.

Let's try generating candidates for a password that consists of one uppercase letter followed by one digit. The mask for this would be ?u?d.

Use the --stdout option again to see the output:

hashcat -a 3 ?u?d --stdout

Hashcat will generate all combinations of one uppercase letter followed by one digit. Note that the output order may appear random due to Hashcat's optimization algorithms, but it will generate all combinations from A0 through Z9.

...
B4
C7
D2
...

By combining these character sets, you can define a precise pattern for the passwords you want to test.

Launch a mask attack for a 3-digit PIN (NTLM hash)

In this step, you will apply your knowledge to a real-world scenario: cracking a 3-digit PIN. We have a file named pin_hash.txt which contains a password hash in NTLM format. We suspect the original password is a 3-digit number.

First, let's view the contents of the hash file:

cat pin_hash.txt

You will see the NTLM hash:

D2063C28444B9B742B9B89C282395EBF

To crack this, we need to tell Hashcat three things:

  1. The attack mode is mask attack (-a 3).
  2. The hash type is NTLM (-m 1000).
  3. The mask for a 3-digit PIN is ?d?d?d.

Now, combine these into a single command to start the attack:

hashcat -a 3 -m 1000 pin_hash.txt ?d?d?d

Hashcat will start, and because the keyspace (000-999) is very small, it will find the password almost instantly.

...
D2063C28444B9B742B9B89C282395EBF:137
...
Status...........: Cracked
...

Hashcat has successfully recovered the password: 137. Once a password is cracked, Hashcat saves it to a file called a "potfile". You can view all cracked passwords for this hash type with the --show option:

hashcat -m 1000 pin_hash.txt --show

Output:

D2063C28444B9B742B9B89C282395EBF:137

Create a custom mask for a known password pattern

In this step, you'll tackle a more complex password. Imagine a company has a password policy: "Passwords must consist of exactly 5 lowercase letters." An example password would be labex.

We have the NTLM hash for such a password in the file pattern_hash.txt.

First, let's translate the password policy into a Hashcat mask:

  • All 5 characters must be lowercase letters: ?l?l?l?l?l

This gives us the final mask: ?l?l?l?l?l.

Now, let's use this mask to crack the hash in pattern_hash.txt. The command is similar to the previous step, but with our new mask.

hashcat -a 3 -m 1000 pattern_hash.txt ?l?l?l?l?l

Hashcat will begin testing all combinations that fit this specific pattern. This is much more efficient than a pure brute-force attack trying all 5-character combinations. After a short time, it will find the password.

...
2BF7D33EC706798E0308F5DF34BC7D2F:labex
...
Status...........: Cracked
...

You have successfully cracked a password with a specific pattern by creating a custom mask that precisely matches the required policy of 5 lowercase letters.

Compare the performance of mask attacks vs. dictionary attacks

In this final step, we will compare the mask attack you just performed with a traditional dictionary attack to understand their respective strengths.

A dictionary attack (-a 0) is very fast if the password is in the wordlist. We have a small dictionary file named dict.txt that contains the password from the previous step.

Let's run a dictionary attack against pattern_hash.txt:

hashcat -a 0 -m 1000 pattern_hash.txt dict.txt

Because labex is in dict.txt, Hashcat finds it almost instantly.

hashcat (v6.2.5) starting

OpenCL API (OpenCL 2.0 pocl 1.8  Linux, None+Asserts, RELOC, LLVM 11.1.0, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
=====================================================================================================================================
* Device #1: pthread-Intel(R) Xeon(R) Platinum 8575C, 6808/13680 MB (2048 MB allocatable), 4MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

INFO: All hashes found in potfile! Use --show to display them.

Started: Sat Oct 11 16:05:20 2025
Stopped: Sat Oct 11 16:05:20 2025

Hashcat informs us that the hash was already found and stored in the potfile. To see the cracked password, we can use the --show option:

hashcat -a 0 -m 1000 pattern_hash.txt dict.txt --show

Output:

2bf7d33ec706798e0308f5df34bc7d2f:labex

So, when does a mask attack have the advantage? A dictionary attack will only succeed if the exact password exists in the wordlist. If the password was testx instead, and that wasn't in our dictionary, the attack would fail.

However, the mask attack from Step 4 (?l?l?l?l?l) would still succeed because it systematically generates and tests all passwords that fit the pattern, regardless of whether they are in a dictionary. It would test labex, testx, hello, and so on.

Conclusion:

  • Dictionary Attack (-a 0): Best for cracking common passwords or when you have a high-quality, targeted wordlist. It's fast but limited by the dictionary's contents.
  • Mask Attack (-a 3): Best when you know the password's structure or pattern (e.g., from a known password policy). It is far more comprehensive than a dictionary attack and infinitely more efficient than a pure brute-force attack.

Summary

In this lab, you have gained hands-on experience with one of Hashcat's most powerful features: the mask attack.

You learned:

  • The fundamental concept of a mask attack (-a 3) and how it generates password candidates based on a pattern.
  • How to use Hashcat's built-in character sets (?l, ?u, ?d, ?s) to construct masks.
  • How to apply a simple mask to crack a 3-digit PIN.
  • How to create a custom mask based on a known password policy (5 lowercase letters) to crack a password with a specific pattern.
  • The key differences and strategic advantages of using a mask attack compared to a standard dictionary attack.

Mask attacks are an essential skill for any security professional, providing a perfect balance between the speed of a dictionary attack and the comprehensiveness of a pure brute-force attack.