I’ve been using Hashcat since I’ve been pentesting at my previous jobs, but I haven’t had the need to use it for a couple of years now. Recently I had another use case for it but I still don’t need to use nearly as often as I once did. I therefore decided to document some of this to easily look things up in the future.
Extracting All Hashes from Active Directory
To copy all hashes from Active Directory, you need domain administrator credentials. Once acquired, make a copy like so:
C:\> ntdsutil "ac i ntds" "ifm" "create full c:\extract" quit quit
C:\> dir c:\extract\Active Directory\ntds.dit
C:\> dir c:\extract\Registry\SYSTEM
Now move both the ntds.dit
and SYSTEM
files to your workstation.
On your workstation, extract the hashes:
user $ secretsdump.py -system SYSTEM -ntds ntds.dit -history > hashes.txt
Once extracted you can start cracking.
Dictionary Attack
Note
|
See this article to understand the difference between LM, NTHash, NTLMv1 and NTLMv2. |
Assuming your extract contains NTHash hashes, you can start a simple dictionary attack like so (using a screen
session):
user $ hashcat -m 1000 -w 3 -a 0 -p : --session=audit --username -o \
cracked.out --outfile-format=3 --potfile-path hashcat.pot hashes.txt \
dict.txt
-m 1000
|
1000 is the NTHash hash type |
-a 0
|
Dictionary attack |
-p :
|
Delimiter in the hashes |
--session=audit
|
Just a session name |
--username
|
Every row in the hash file first starts with a username |
-o cracked.out
|
Keeps track of accounts of which the hashes are cracked |
--outfile-format-3
|
Output file format |
--potfile-path hashcat.pot
|
Saves all cracked hashes in a separate pot file. |
I found several good wordlists over the past couple of years:
-
https://github.com/danielmiessler/SecLists: home of the well-known SecLists
-
https://github.com/l33kzplus/breach-links: several magnet links to real breaches
-
https://github.com/initstring/passphrase-wordlist: passphrase dict and rules
-
https://weakpass.com/: lots of wordlists
-
https://crackstation.net/crackstation-wordlist-password-cracking-dictionary.htm: real passwords
-
https://hashmob.net/resources/hashmob: real passwords from a cracking community
-
https://github.com/spipm/Dutch-Password-List: Dutch wordlists
Rule Based Attack
This adds rules (common substitutions) to the cracking attack. For example, candidate 'password123' in the dictionary, a rule could also produce candidate 'P@$$w0rd2024!'. Observe that a rule could do some common leetspeak substitutions, replace the digits with the current year, and add a common symbol at the end.
user $ hashcat -m 1000 -w 3 -a 0 -p : --session=audit --username -o \
cracked.out --outfile-format=3 --potfile-path hashcat.pot hashes.txt \
dict.txt -r rules.txt
Notice the -r rules.txt
option, to specify a rule file.
Apart from the standard rules (e.g. d3ad0ne, dive, etc.), I found several other rules that proved quite useful:
-
https://github.com/NotSoSecure/password_cracking_rules: home of the well-known OneRuleToRuleThemAll
-
https://github.com/stealthsploit/OneRuleToRuleThemStill: a revamped and optimised version
-
https://github.com/NSAKEY/nsa-rules: based on statistics and compromised passwords
-
https://github.com/praetorian-inc/Hob0Rules: based on statistics and industry patterns
-
https://github.com/rarecoil/pantagrule: lots of rules generated from compromised passwords
-
https://github.com/Unic0rn28/hashcat-rules: similar to OneRuleToRuleThemAll, but more recent and more large scale
-
https://github.com/caeksec/rules: huge miscellaneous collection, also including the above
Mask Based Attack
A brute force attack of sorts, trying all characters in a given character space.
user $ hashcat -m 1000 -w 3 -a 3 -p : --session=audit --username -o \
cracked.out --outfile-format=3 --potfile-path hashcat.pot hashes.txt \
'?u?l?l?l?l?d?d?d?d?s'
Notice the -a 3
option (mask attack mode), and '?u?l?l?l?l?d?d?d?d?s'
(the actual mask, here 1 upper, 4 lower, 4 digits, 1 symbol).
Hybrid Attack
Using a dictionary, and a mask:
user $ hashcat -O -m 1000 -w 3 -a 6 -p : --username --session=hybrid -o \
cracked.out --outfile-format=3 --potfile-path hashcat.pot hashes.txt \
dict.txt '?d?d?s'
Notice the '-a 6' option (hybrid mode), and the mask at the end. Here the mask is appended to each candidate from the dictionary.
Combinator Attack
This attacks uses more than 1 dictionary to generate candidates. It concatenates words from both dicts, and optionally applies a single rule per dict as well:
user $ hashcat -O -m 1000 -w 3 -a 1 -p : --username --session=combinator -o \
cracked.out --outfile-format=3 --potfile-path hashcat.pot hashes.txt \
dict1.txt -j '$-' dict2.txt -k '$!'
Notice the -a 1
option (combinator mode), and the 2 dicts at the end.
The -j '$-'
option applies a single rule (appending a dash) to the left word.
The -k '$!'
option applies another single rule (appending an exclamation mark) to the right word.
In this example, this would produce candidates comprising of 2 words, separated with a dash, and suffixed with an exclamation mark.
You can also use complete rule files, but AFAIK you cannot use Hashcat’s built-in combinator mode.
You’d need to use the combinator
tool to concatenate words for 2 or more dicts, and pipe the output to hashcat:
user $ combinator dict1.txt dict2.txt | hashcat -O -m 1000 -w 0 -a 0 -p : \
--username --session=combinator -o cracked.out --outfile-format=3 \
--potfile-path hashcat.pot hashes.txt -r rules.txt
Custom Dictionaries
The ntds.dit
file might also contain some CLEARTEXT passwords:
user $ grep CLEARTEXT hashes.txt | cut -d : -f 3 | sort -u >> cleartext.txt
Once you’ve cracked enough hashes from your set of hashes, you could also generate a dict comprising of those discovered passwords:
user $ cut -d : -f 2 hashcat.pot > cracked-dict-history-uniq
Another valuable tip I got from colleagues in the field is to generate a wordlist from Wikipedia, using WikiRaider.
Currently this tool no longer works, but I found a fork which did some improvements. That fork also doesn’t work anymore, but I found an easy fix. I forked it, fixed it, and created a pull request, but currently it’s not merged yet. For the time being you could use my fork, or manually apply this commit to the SmallKingfisher repo.
Once you’ve cloned the repo, you can create a wordlist like so:
user $ ./wikiraider.py parse -u https://dumps.wikimedia.org/nlwiki/20240901
Note
|
This might take a (very) long time (hours, plural) and may use several GiBs (tens, even) of space, depending on how large the database is. |
You can also create smartlists using cracken.
This splits words like HelloWorld123!
into words like ['Hello', 'World', '123!']
:
user $ cracken create -f cracked-dict-history-uniq -o smartlist
Password Analysis
Once you’re done cracking you can do some password analysis, for example:
-
most commonly used passwords
-
most commonly used words
-
password length distribution
-
etc.
You could use pipal for this:
user $ hashcat -m 1000 --show --username hashes.txt --potfile-path \
hashcat.pot | grep -v 'Failed to parse hashes using the \'pwdump\'
format.' | grep -v '^$' | cut -d : -f 3 | sed 1,7d | grep -v '^$' | \
sort > cracked-dict.txt
user $ pipal cracked-dict.txt --top 10
Basic Results
Total entries = xxxx
Total unique entries = xxxx
Top 10 passwords
xxxxxxxxxxxx = 295 (7.15%)
xxxxxxxxxxxxxxx = 48 (1.16%)
xxxxxxxxxxxxx = 30 (0.73%)
xxxxxxxxxxxxx = 30 (0.73%)
xxxxxxxxxxxxx = 28 (0.68%)
xxxxxxxxxxxxxxxxxxxx = 26 (0.63%)
xxxxxxxxxxxxxx = 24 (0.58%)
xxxxxxxxxxxxxxxx = 20 (0.48%)
xxxxxxxxxxxxxxxxx = 17 (0.41%)
xxxxxxxxxxxxx = 16 (0.39%)
Top 10 base words
xxxxxxxxx = 386 (9.35%)
xxxxxxxxxxxx = 111 (2.69%)
xxxxxxxxxxxxxxxx = 45 (1.09%)
xxxxxxxx = 43 (1.04%)
xxxxxxxxx = 34 (0.82%)
xxxxxxxxx = 34 (0.82%)
xxxxxxxx = 30 (0.73%)
xxxxxxxxxx = 30 (0.73%)
xxxxxxxx = 28 (0.68%)
xxxxxxxxxxxx = 27 (0.65%)
You could also analyse your passwords for probable masks using statsgen
from PACK:
user $ statsgen cracked-dict.txt
[...]
[*] Advanced Masks:
[+] ?l?l?l?l?l?l?l?l: 04% (687991)
[+] ?l?l?l?l?l?l: 04% (601152)
[+] ?l?l?l?l?l?l?l: 04% (585013)
[+] ?l?l?l?l?l?l?l?l?l: 03% (516830)
[+] ?d?d?d?d?d?d?d: 03% (487429)
[...]
If accounts are using a consistent naming convention, you can also check how many you cracked of a certain type. For example:
user $ hashcat -m 1000 --show --username hashes.txt --potfile-path \
hashcat.pot | grep -i 'company.n(et|l).(acc|ext)[0-9]{6}' | sort | \
wc -l