Hashcat
Hashcat takes a hash you already captured and recovers the plaintext behind it by hashing millions of candidates per second on the GPU and comparing. Reach for it once the hash is in hand: a dumped NTLM or shadow entry from a CTF box, a captured WPA handshake in a homelab, or a Kerberoast ticket from an authorized assessment. The hard part is never the cracking itself, it is picking the exact hash mode and a sane candidate strategy.
Mental model: hashcat -m MODE -a ATTACK HASH_FILE [WORDLIST|MASK]. Get -m right first; everything else is candidate strategy.
New to hashing? Core concepts
- Hash mode (
-m): the exact algorithm, for example0MD5,1000NTLM,1800sha512crypt,22000WPA. The wrong mode never cracks. - Attack mode (
-a): how candidates are generated:0dictionary,1combinator,3mask (brute force),6/7hybrid (wordlist plus mask) - Wordlist: a file of likely passwords, one per line, such as
/usr/share/wordlists/rockyou.txt - Rule (
-r): mutates each word (capitalize, append digits, leetspeak) so one base word covers many real variants - Mask: a pattern of charset tokens:
?llower,?uupper,?ddigit,?ssymbol,?aany of those - Keyspace: how many candidates an attack produces; a full eight-char
?amask is astronomical, a focused mask is tiny - Potfile:
hashcat.potfile, where cracks are recorded so--showreprints them later without redoing work - Salt and slow hashes: bcrypt and sha512crypt are salted and deliberately slow; MD5 and NTLM are fast
When to reach for Hashcat (and when not)
Reach for it once you already hold the hash: a dumped NTLM or shadow entry, a WPA handshake, a Kerberoast or AS-REP ticket, or to prove a weak password policy with hashes pulled under authorization. It is the fastest GPU cracker with the richest rule and mask engine.
Reach for something else when you first need to turn a file into a hash (John the Ripper’s *2john helpers, or hcxpcapngtool for Wi-Fi captures), when you have no GPU and want smart CPU defaults (John), when a default credential or a pass-the-hash avoids cracking entirely, or when the policy guarantees long random secrets and brute force is hopeless.
Install, update, verify#
sudo apt install -y hashcat # Debian / Ubuntu / Kali
sudo dnf install -y hashcat # Fedora / RHEL
brew install hashcat # macOS
sudo apt install --only-upgrade -y hashcat # update
hashcat --version # version string
command -v hashcat # confirm it is on PATH
hashcat -I # list backend devices (GPU/CPU) and the OpenCL/CUDA runtime
hashcat -b -m 0 # self-test: benchmark MD5, prints a hashes/sec number
Full GPU speed needs current drivers plus the matching OpenCL or CUDA runtime; hashcat -I should show at least one usable device. For a hash mode added in a recent release, grab the upstream binary from hashcat.net and run it in place instead of the repo package.
Flags you’ll actually use#
Skim these first; the cheat sheet below is these flags combined.
| Flag | Does | Flag | Does |
|---|---|---|---|
-m | Hash mode (algorithm), set it first | -a | Attack mode (0/1/3/6/7) |
-r | Apply a rule file | -w | Workload profile (1-4) |
--show | Print cracked hashes from the potfile | --left | Print the hashes still uncracked |
-o | Write cracks to a file | --username | Ignore the user column in user:hash |
-i | Increment mask length | --keyspace | Count candidates, do not run |
--session | Name a job | --restore | Resume a named job |
-1..-4 | Define a custom charset | --stdout | Print candidates, do not crack |
-O | Optimized kernel (caps password length) | -I | List backend devices |
-b | Benchmark a mode | --identify | Suggest the hash mode |
--potfile-disable | Ignore the potfile this run | --remove | Delete cracked lines from the hash file |
Cheat sheet#
Each dictionary and mask block starts bare and adds one flag at a time, so you can stop at the line that does the job.
# Identify the hash, then benchmark the mode
hashcat --identify HASH_FILE # built-in mode guesser (lists candidate -m numbers)
hashcat -b -m 1000 # benchmark NTLM, gauge candidates/sec
# Build up a dictionary attack: stop at the line you need
hashcat -m 1000 HASH_FILE WORDLIST # 1. plain dictionary (-a 0 is default)
hashcat -m 1000 HASH_FILE WORDLIST -r /usr/share/hashcat/rules/best64.rule # 2. + one rule set
hashcat -m 1000 HASH_FILE WORDLIST \
-r /usr/share/hashcat/rules/best64.rule -r /usr/share/hashcat/rules/d3ad0ne.rule # 3. + stack a second rule
hashcat -m 1000 HASH_FILE WORDLIST -O -w 3 # 4. + optimized kernel, high workload
# Mask attacks (brute force by pattern)
hashcat -m 0 -a 3 HASH_FILE ?d?d?d?d?d?d # exactly six digits (1,000,000 candidates)
hashcat -m 0 -a 3 HASH_FILE ?u?l?l?l?l?d?d # Capital + 4 lower + 2 digits, e.g. Admin12
hashcat -m 0 -a 3 -i HASH_FILE ?d?d?d?d?d?d?d?d # increment: 1..8 digits, short first
hashcat -m 0 -a 3 -1 ?l?d HASH_FILE ?1?1?1?1?1 # custom charset (?1 = lowercase + digit)
hashcat -m 0 -a 3 --keyspace ?a?a?a?a?a?a?a?a # count candidates before committing
# Hybrid attacks (word + mask)
hashcat -m 0 -a 6 HASH_FILE WORDLIST ?d?d?d?d # word then four digits (Summer2026)
hashcat -m 0 -a 7 HASH_FILE ?d?d?d?d WORDLIST # four digits then word
# Real hash types you will meet
hashcat -m 1000 HASH_FILE WORDLIST # NTLM (secretsdump, SAM)
hashcat -m 1800 HASH_FILE WORDLIST # sha512crypt, Linux /etc/shadow ($6$)
hashcat -m 3200 HASH_FILE WORDLIST # bcrypt ($2*$), slow and salted
hashcat -m 22000 HASH_FILE WORDLIST # WPA/WPA2 (from hcxpcapngtool)
hashcat -m 13100 HASH_FILE WORDLIST # Kerberoast TGS-REP
hashcat -m 18200 HASH_FILE WORDLIST # AS-REP roast
hashcat -m 5600 HASH_FILE WORDLIST # NetNTLMv2 (Responder capture)
# Files in user:hash format
hashcat -m 1000 --username HASH_FILE WORDLIST # ignore the leading user column
# Long jobs: name and resume
hashcat --session box01 -m 1000 HASH_FILE WORDLIST -o cracked.txt # name + save cracks
hashcat --session box01 --restore # resume after a stop
# Read results without cracking again
hashcat -m 1000 --show HASH_FILE # print hash:plaintext from the potfile
hashcat -m 1000 --left HASH_FILE # print the hashes still uncracked
# Debug candidates before spending GPU time
hashcat -a 0 --stdout WORDLIST -r /usr/share/hashcat/rules/best64.rule # show the exact mutated words
Command breakdowns#
Each block below explains one situation, the exact command, and what to expect back.
Identify the hash type before you start#
hashcat --identify HASH_FILE
Prints the candidate -m numbers Hashcat thinks the string could be. It narrows the field but does not decide; a 32-char hex string is MD5 (0) or NTLM (1000) or many others. Cross-check with hashid or name-that-hash, and the source (a Windows dump is NTLM, a $6$ prefix is sha512crypt).
Benchmark a mode to estimate the run time#
hashcat -b -m 1000
Prints NTLM candidates/sec for your hardware. Divide your keyspace by that number for a rough ETA before you commit GPU hours. Fast modes (MD5, NTLM) run billions/sec; bcrypt runs thousands.
Run a straight dictionary attack#
hashcat -m 1000 HASH_FILE WORDLIST
The first thing to try, and often the only thing you need. -a 0 is the default, so it is implied. Set -m to the real algorithm; 1000 here is NTLM. WORDLIST is a file like rockyou.txt.
Add rules to cover common mutations#
hashcat -m 1000 HASH_FILE WORDLIST -r /usr/share/hashcat/rules/best64.rule
Rules turn password into Password, password1, p@ssw0rd, and so on, multiplying one base word into many. Stack more with a second -r; the counts multiply, so watch the keyspace.
Brute force a known pattern with a mask#
hashcat -m 0 -a 3 HASH_FILE ?d?d?d?d?d?d
-a 3 is mask mode. ?d is one digit, so this is exactly 1,000,000 six-digit candidates, tiny and instant. Build the mask to match a known shape: ?u?l?l?l?l?d?d for Admin12.
Grow the mask length with increment#
hashcat -m 0 -a 3 -i HASH_FILE ?d?d?d?d?d?d?d?d
-i (--increment) tries length 1 first, then 2, up to the mask width, instead of only the full eight digits. Add --increment-min/--increment-max to bound the sweep.
Build a custom charset for a mask#
hashcat -m 0 -a 3 -1 ?l?d HASH_FILE ?1?1?1?1?1
-1 ?l?d defines charset 1 as lowercase plus digits; ?1 then uses it per position. This is how you brute force a realistic keyspace (letters and numbers) without the symbol blowup of ?a.
Combine a word and a mask (hybrid)#
hashcat -m 0 -a 6 HASH_FILE WORDLIST ?d?d?d?d
-a 6 appends the mask after each word, catching Summer2026 style passwords. -a 7 prepends it instead (2026Summer). This covers the extremely common “word plus a few digits” pattern that plain dictionaries miss.
Crack NTLM from a user:hash dump#
hashcat -m 1000 --username user_ntlm.txt WORDLIST -r /usr/share/hashcat/rules/best64.rule
--username ignores the left column so Hashcat reads only the hash. From full secretsdump output (domain\user:rid:lm:nt:::), pull the NT column first with cut -d: -f4 dump.txt > user_ntlm.txt.
Crack a Linux shadow hash#
hashcat -m 1800 HASH_FILE WORDLIST
-m 1800 is sha512crypt, the $6$... entries in /etc/shadow. It is salted and slow, so lead with a focused dictionary and best64 rules rather than a broad mask. Copy only the $6$... field into HASH_FILE.
Crack a WPA/WPA2 handshake#
hcxpcapngtool -o wifi.22000 capture.pcapng
hashcat -m 22000 wifi.22000 WORDLIST
Convert the capture to the 22000 format first with hcxpcapngtool (from hcxtools), then crack. Mode 22000 replaced the old 2500/16800. WPA keys are 8 to 63 chars, so a good wordlist beats any mask here.
Crack a Kerberoast ticket#
hashcat -m 13100 tgs.txt WORDLIST -r /usr/share/hashcat/rules/best64.rule
-m 13100 cracks the $krb5tgs$23$... strings you collect from GetUserSPNs.py or Rubeus. For AS-REP roasting ($krb5asrep$...) use -m 18200. Both recover a service or user account password.
Estimate keyspace before a big mask#
hashcat -m 0 -a 3 --keyspace ?a?a?a?a?a?a?a?a
Prints a single number: the total candidates. Divide by your benchmark speed; if the answer is years, narrow the mask, add a custom charset, or fall back to dictionary plus rules.
Name a session and resume it later#
hashcat --session box01 -m 1000 HASH_FILE WORDLIST -o cracked.txt
hashcat --session box01 --restore
--session writes a restore point so a long job survives a reboot or a q. Resume with the same session name and --restore. Always pair long runs with -o so results land in a file.
Read what already cracked, and what is left#
hashcat -m 1000 --show HASH_FILE
hashcat -m 1000 --left HASH_FILE
--show reads the potfile and prints hash:plaintext, read-only and instant, no GPU needed. --left prints the hashes that have not fallen yet, ready to pipe into the next, harder attack.
Preview candidates with –stdout#
hashcat -a 0 --stdout WORDLIST -r /usr/share/hashcat/rules/best64.rule
Prints the exact mutated words a rule or mask would try, without cracking anything. Use it to sanity-check a rule file or a custom charset before spending real GPU time on it.
Reading the status screen#
- Status: Running - the attack is in progress; watch Speed and Progress.
- Status: Cracked - every hash in the file fell. You are done with that set.
- Status: Exhausted - all candidates were tried and some hashes remain. Change the attack, not the mode.
- Recovered: 2/5 - hashes cracked out of the total (a second count tracks salts).
- Speed - candidates/sec; compare it to the keyspace for a live ETA.
- Progress - candidates done out of total, with a percent.
- High speed, zero cracks - not an error; your candidate strategy missed the real password. Fix the wordlist, rules, or mode.
- Interactive keys during a run:
sstatus now,ppause,rresume,bbypass this attack,ccheckpoint (quit at the next restore point),qquit.
Cracked lines print as hash:plaintext, or hash:salt:plaintext for salted modes, both to the screen and to any -o file.
Troubleshooting#
| Problem | Cause | Fix |
|---|---|---|
command not found | Not installed / stale PATH | Reinstall; open a fresh shell |
No devices found/left | Missing GPU driver or runtime | Install OpenCL/CUDA, or force CPU with -D 1 |
Token length exception | Wrong -m or malformed line | Verify the mode; strip blank lines and CRLF |
Separator unmatched | user:hash fed as a raw hash | Add --username or cut out the column |
Not enough allocatable device memory | Mask or wordlist too big for VRAM | Lower -w, drop -O, or split the job |
| Status hits Exhausted, no crack | Candidate strategy too narrow | Add rules, a bigger wordlist, or a mask |
| Runs but painfully slow | Slow salted mode or CPU-only | Expected for bcrypt; use the GPU, tune -w |
--show prints nothing | No cracks yet or wrong -m | Confirm the mode; let the attack finish |
Self-test failed | Driver or kernel mismatch | Update drivers; try the upstream binary |
Gotchas#
- The mode is everything. A wrong
-mruns at full speed and cracks nothing, so a “high speed, zero cracks” run is almost always the mode, not the wordlist. -O(optimized kernel) silently caps password length, often at 31 and shorter for some modes. It is much faster but skips longer candidates, so drop it if a password you know is long never falls.- The potfile hides “already cracked” hashes. A re-run can look like it did nothing because Hashcat skips potfile hits; use
--showto see them or--potfile-disableto force a fresh run. -a 3masks are position-locked.?d?d?d?dmatches only four-digit passwords, never “up to four”; use-ito sweep lengths.- CRLF line endings break input.
rockyou.txtor a hash file saved on Windows carries\r, which triggers token and line-length errors; keep both LF-only. - WPA moved to mode 22000. Old guides use
2500/16800with.hccapxor.pmkid; convert captures withhcxpcapngtooland use22000instead.
Pairs with#
hashid, name-that-hash, or hashcat --identify name the algorithm so you set -m right the first time. John the Ripper’s *2john helpers (zip2john, ssh2john, keepass2john) turn files into crackable hashes, and John is the better CPU-only default. hcxtools (hcxpcapngtool) converts Wi-Fi captures into mode 22000. SecLists supplies realistic wordlists and rules, while cut and awk pull the hash column out of a dump before you feed it in.