Writing custom wordlists using hashcat and cuppy
Introduction
this post highlights the power of custom wordlists,
Instead of relying on generic, multi-gigabyte wordlists, we will perform a targeted attack.
This highly effective strategy uses Open Source Intelligence (OSINT) to create a custom wordlist and ruleset tailored specifically to our victim.
We can use Hashcat to combine lists of potential names and labels with specific mutation rules to create custom wordlists.
Hashcat uses a specific syntax to define characters, words, and their transformations. The complete syntax is documented in the official Hashcat rule-based attack documentation, but the examples below are sufficient to understand how Hashcat mutates input words.
Function | Description |
---|---|
: |
Do nothing |
l |
Lowercase all letters |
u |
Uppercase all letters |
c |
Capitalize the first letter and lowercase others |
sXY (leet) |
Replace all instances of X with Y |
$! |
Add the exclamation character at the end |
$0, $9 | appends numbers |
$1$9$9$8 | translates to 1998 |
t |
Toggle the case of all characters in word p@ssW0rd->P@SSw0RD |
Each rule is written on a new line and determines how a given word should be transformed. If we write the functions shown above into a file, it may look like this:
We can use the following command to apply the rules in custom.rule
to each word in password.list
and store the mutated results in mut_password.list
.
1 | magdy3660@htb[/htb]$ hashcat --force password.list -r custom.rule --stdout | sort -u > mut_password.list |
password cracking and the creation of custom wordlists are, in most cases, a guessing game. We can narrow this down and perform more targeted guessing if we have information about the password policy, while considering factors such as the company name, geographical region, industry, and other topics or keywords that users might choose when creating their passwords. Exceptions, of course, include cases where passwords have been leaked and directly obtained.
Generating wordlists using CeWL
We can use a tool called CeWL to scan potential words from a company’s website and save them in a separate list. We can then combine this list with the desired rules to create a customized password list—one that has a higher probability of containing the correct password for an employee. We specify some parameters, like the depth to spider (-d
), the minimum length of the word (-m
), the storage of the found words in lowercase (--lowercase
), as well as the file where we want to store the results (-w
).
Writing Custom Wordlists and Rules
1 | $ cewl https://www.inlanefreight.com -d 4 -m 6 --lowercase -w inlane.wordlist |
Welcome to this hands-on lab where we’ll crack a password hash by building a targeted wordlist. Instead of relying on generic, multi-gigabyte wordlists, we will perform a targeted attack. This highly effective strategy uses Open Source Intelligence (OSINT) to create a custom wordlist and ruleset tailored specifically to our victim.
This exercise will show you how to combine intelligence gathering with the power of cuppy
and hashcat
to compromise a password under a corporate policy.
SECTION EXERCISE
The Scenario
Imagine we have compromised a password hash from the work email of a target named Mark White. Through some basic OSINT, we’ve gathered the following details:
- Name: Mark White
- Birth Date: August 5, 1998
- Employer: Nexura, Ltd.
- Company Password Policy:
- Minimum 12 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one symbol
- Location: San Francisco, CA, USA
- Personal Details:
- Wife:
Maria
- Son:
Alex
- Pet Cat:
Bella
- Hobby:
baseball
- Wife:
The Target Hash (MD5): 97268a8ae45ac7d15c3cea4ce6ea550b
Generating a Base Wordlist with cuppy
first we need to convert our OSINT data into a list of potential password keywords. The Common User Passwords Profiler (cuppy
) is the perfect tool for this job. It takes personal information as input and generates a wordlist based on common patterns.
Run cuppy
in interactive mode and enter the information we gathered about Mark.
1 | cuppy -i |
1 | $ wc -l mark.txt |
Creating hashcat rules
We’ll create a file named custom.rule
to add the required complexity (capitalization, numbers, symbols).
Instead of only guessing the most obvious pattern, we’ll create a broader set of rules. This will generate a very large number of candidates, increasing our chances of success if the user chose a slightly less common pattern.
Here is an example of a more comprehensive custom.rule
file. It includes capitalization, leetspeak substitutions (s
for $
, a
for @
), and appending various years and symbols.
1 | # custom.rule - A broad ruleset for our target |
Note: Your own rule file might be much larger to generate all the possibilities.
Applying Rules and Filtering the Wordlist
Now, let’s apply our custom.rule
file to the mark.txt
wordlist. We’ll use hashcat
with the --stdout
flag to output all the generated password candidates and save them to a new file. The sort -u
command removes any duplicates.
1 | hashcat --force mark.txt -r custom.rule --stdout | sort -u > mut_password.list |
This process will create a huge list of mutated passwords. Let’s see the result.
1 | cat mut_password.list | grep -E '^.{12,}$' | grep -E '[A-Z]+[a-z]+' | sort -u > 12ormore.txt |
grep -E '^.{12,}$'
finds all lines with 12 or more characters.grep -E '[A-Z]+[a-z]+'
ensures there’s at least one uppercase letter followed by a lowercase, a common pattern for capitalization.
This filtering step is crucial for reducing the noise
1 | $ wc -l 12ormore.txt |
We are now left with a final list of over 190,000 strong candidates that are much more likely to be correct. Let’s peek at the first few lines to ensure they look right.
1 | $ head -n 3 12ormore.txt |
Cracking the Hash
This is the moment of truth. We will now use our final, filtered wordlist (12ormore.txt
) against the target hash.
1 | $hashcat -m 0 97268a8ae45ac7d15c3cea4ce6ea550b 12ormore.txt |
Result:
Once hashcat
finishes, its status will show Cracked
. To view the plaintext password you just discovered, use the --show
flag.
1 | $ hashcat -m 0 97268a8ae45ac7d15c3cea4ce6ea550b --show 97268a8ae45ac7d15c3cea4ce6ea550b:Ba******! |
(full doc:https://hashcat.net/wiki/doku.php?id=rule_based_attack)
Function | Description |
---|---|
: |
Do nothing |
l |
Lowercase all letters |
u |
Uppercase all letters |
c |
Capitalize the first letter and lowercase others |
sXY (leet) |
Replace all instances of X with Y |
$! |
Add the exclamation character at the end |
$0, $9 | appends numbers |
$1$9$9$8 | translates to 1998 |
t |
Toggle the case of all characters in word p@ssW0rd->P@SSw0RD |
1 | --- SECTION 3: Leetspeak (Character Substitution) --- |
so when writing the rules, they would look like this:
1 | Creates passwords like: Baseball1998!, |
apply the rule to the wordlist:
1 | $ hashcat --force password.list -r custom.rule --stdout | sort -u > mut_password.list |
hmm, lets see how many words we have
1 | $ wc -l mut_password.list |
now lets further customize it for our password policy since there maybe huge amount of junk that wouldn’t work, by grepping for words with 12 or more characters:
1 | $ cat mut_password.list | grep -E '^.{12,}$' | grep -E '[A-Z]+[a-z]+' | sort -u > 12ormore.txt |
okay but how does each word look like?
1 | $ head -n 50 12ormore.txt |
i kept it this way as mark may have set the symbols firstly, but the symbols in the beginning could be removed and replaced with uppercase in the beginning with: grep -E '^[A-Z]'
now lets put it all to the test:
1 | $ hashcat -m 0 97268a8ae45ac7d15c3cea4ce6ea550b 12ormore.txt |
1 | $ hashcat -m 0 97268a8ae45ac7d15c3cea4ce6ea550b 12ormore.txt --show |
Success! The output above is redacted to let you discover the answer on your own. On your screen, you should see the full, cracked password. You’ll notice it perfectly matches the intelligence we gathered—a keyword from the victim’s life, combined with numbers and a symbol to meet the corporate policy
Key Takeaways
- OSINT is Power: Good intelligence gathering is the most critical step in a targeted attack.
- Humans are Predictable: Users often follow simple patterns to meet “complex” password policies, which we can replicate with
hashcat
rules. - Filtering is Efficiency: A broad ruleset creates many possibilities, but filtering for the known policy requirements is what makes the attack fast and effective.