Step 124. Password Attack 3 — hashcat and Attack Modes

Step 124. Password Attack 3 — hashcat and Attack Modes

Level 2 — Introduction to Security and Attack Skill Basics | Difficulty ★★★☆☆ | Estimated time: 3 hours

Prerequisites: john and hash-format identification ($6$, etc.) from Steps 122–123, and the combinatorial math from Step 49.

  • What you need: a Linux environment (WSL works), Python 3. This chapter’s hashcat screens are screen examples from a GPU lab; hash generation and combination counting are measured directly on your computer.
  • ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.

In Step 123 you cracked shadow hashes with john. But the field has a bigger beast — hashcat, the final boss of cracking tools, mobilizing a GPU’s thousands of compute cores to submit tens of billions of candidates per second. Today’s core question is one — "how do you find a password you don’t know?" The answer is "try them all," and hashcat is the technology of how fast and how smartly you do that trying. Choosing the attack mode you’ll learn today turns cracking time from seconds to years, and from years to seconds.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Explain why GPU cracking is faster than CPU, in terms of core structure
  • Know the meaning of per-hash-type mode numbers (-m) and attack modes (-a 0/1/3)
  • Choose and run dictionary and mask attacks appropriately for the situation
  • Calculate a mask’s combination count yourself and estimate "time to crack"
  • Avoid preparation-stage traps like echo -n and produce correct hashes

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment Linux shell + Python 3 (for measuring combination counts)
Today’s tools hashcat (screen examples), md5sum, hashlib (measured)
Today’s commands hashcat -m 0 -a 0 hash dict, hashcat -m 0 -a 3 hash mask, --show
Concepts needed GPU parallel computation, hash mode numbers, mask charsets (?l ?u ?d ?a), combinatorial explosion
Today’s artifact A mode-selection criteria table + a combination-counting practice note

2-1. Why the GPU — A Thousand Simple Workers

A CPU is a few smart workers; a GPU is a factory of thousands of simple workers. Hash cracking is the infinite repetition of one simple job — "hash a candidate and compare" — so the more dim-witted workers you have, the better. While one mid-range graphics card tries MD5 tens of billions of times per second, a CPU hovers around ten million. That’s why the same hash comes with a time difference of thousands of times.

That said, this speed varies wildly by hash type. Hashes "designed to be computed fast," like MD5 and SHA-1, are heaven for GPUs; hashes "designed to be deliberately slow," like bcrypt and yescrypt, leave even GPUs helpless. That’s why modern systems use slow hashes, and why you learned in Step 123 that $y$ (yescrypt) is safer than $1$ (MD5).

2-2. Hash Mode Numbers — Telling hashcat "This Is What Kind of Hash"

hashcat doesn’t guess the type from the hash string alone. You must tell it with a mode number.

Number Hash Example
-m 0 MD5 f30aa7a662c728b7407c54ae6bfd27d1
-m 100 SHA-1 40 hex digits
-m 1800 sha512crypt ($6$) Linux shadow
-m 7400 sha256crypt ($5$) Linux shadow

In a real environment, you find the number by searching the help, like hashcat --help | grep -i md5. Get the number wrong and you’ll get a hash-format error — or silently fail to crack forever.

2-3. Attack Modes — In What Order Will You Generate Candidates?

hashcat’s real skill lies in attack modes. You choose with the -a option.

  • -a 0 dictionary attack: submits a prepared word list from top to bottom. Because human passwords derive from words, this is the mode that cracks first and with the highest probability in the field. The representative dictionary is rockyou.txt, with 14 million leaked passwords.
  • -a 1 combinator attack: concatenates words from two dictionaries. apple + pieapplepie. Aims for passwords made of "two words joined."
  • -a 3 mask attack: exhaustively tries candidates by specifying the shape of each position directly. ?d?d?d?d means "all four-digit numbers" (0000–9999).

Here’s the mask character table (charsets).

Symbol Meaning Character count
?l lowercase a–z 26
?u uppercase A–Z 26
?d digits 0–9 10
?s special characters 33
?a all of the above (printable ASCII) 95

The philosophy of mask attacks is this — "the more you know about the password’s pattern, the fewer attempts you need." Trying all "8 characters of anything" is 95⁸, but knowing the pattern "five lowercase + three digits" makes it 26⁵×10³ — and you’ll soon calculate for yourself how much that shaves off.


3. Follow Along

3-1. Making the Cracking Target — Measuring md5sum

Let’s make a practice hash ourselves (measured 2026-09-09 on WSL):

echo -n "hello123" | md5sum
f30aa7a662c728b7407c54ae6bfd27d1  -

How to read it: this 32-digit hex number is the MD5 of hello123. It’s the value we’ll use as today’s cracking target, so copy it down.

Here’s today’s first trap — what happens if you drop the -n? We measured it.

echo "hello123" | md5sum
0766c52d63e56019890004b598edd005  -

How to read it: a completely different hash came out. By default echo appends a newline character (enter) at the end, and the hash is computed including that newline. Python confirms it too (measured 2026-09-09):

import hashlib
hashlib.md5(b"hello123").hexdigest()    # f30aa7a662c728b7407c54ae6bfd27d1
hashlib.md5(b"hello123n").hexdigest()  # 0766c52d63e56019890004b598edd005

Forget the -n when making a hash, and the tragedy unfolds where you know perfectly well the answer is hello123 yet crack forever at an uncrackable hash. When making a cracking target, always echo -n.

3-2. Dictionary Attack — Reading a Screen Example

Here’s a run in a GPU lab (this environment has no hashcat, so it’s a screen example):

hashcat -m 0 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
...
f30aa7a662c728b7407c54ae6bfd27d1:hello123

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Speed.#1.........: 23411.2 MH/s (0.12ms)

How to read it: look at just three places. ① The cracked result in hash:plaintext form — hello123 has been recovered. ② Status: Cracked. ③ The speed 23411.2 MH/s — meaning 23.4 billion tries per second. Since hello123 is inside rockyou.txt, the dictionary attack finishes in a blink.

3-3. Mask Attack — Exhaustive Trying by Pattern

This time, with no dictionary, we crack using only the pattern information "5 lowercase letters + 3 digits" (screen example):

hashcat -m 0 -a 3 hash.txt "?l?l?l?l?l?d?d?d"
f30aa7a662c728b7407c54ae6bfd27d1:hello123

Progress.........: 11881376000/11881376000 (100.00%)

How to read it: the Progress denominator — 11,881,376,000. The total number of candidates the mask generated. It tried exactly 26⁵×10³. Where did this number come from? We calculate it ourselves in the next section.

3-4. Calculating the Combinatorial Explosion — Python Measurement

Counting a mask’s attempts by hand is today’s core training (measured 2026-09-09 on Python 3.12):

masks = {
    "?d?d?d?d (4 digits)": 10**4,
    "?l?l?l?l (4 lowercase)": 26**4,
    "?l?l?l?l?l?d?d?d (5 lower + 3 digits)": 26**5 * 10**3,
    "?l?l?l?l?l?l?l?l (8 lowercase)": 26**8,
    "?a x8 (any 8 chars)": 95**8,
}
for mask, n in masks.items():
    print(f"{mask:38s} {n:,} tries")
?d?d?d?d (4 digits)                    10,000 tries
?l?l?l?l (4 lowercase)                 456,976 tries
?l?l?l?l?l?d?d?d (5 lower + 3 digits)  11,881,376,000 tries
?l?l?l?l?l?l?l?l (8 lowercase)         208,827,064,576 tries
?a x8 (any 8 chars)                    6,634,204,312,890,625 tries

How to read it: every time the length grows by one, the attempt count is multiplied by the charset size. This is the combinatorial explosion you learned in Step 49, and the reason password length is security itself. Note the 30,000x difference between "8 lowercase letters" (208.8 billion) and "any 8 characters" (6.6 quadrillion) — the numbers tell you why mixing character classes is powerful.

3-5. Estimating "How Long Will It Take" — Multiplying by Speed

Divide the combination count by the speed and you get an estimated time. With speeds set at 10 million/sec for CPU and 50 billion/sec for GPU (rough assumptions for MD5), we calculated (measured 2026-09-09 — speeds are assumptions, combination counts are real calculations):

Mask Attempts CPU (10M/sec) GPU (50B/sec)
?l?l?l?l 456,976 0.05s 0.00s
?l?l?l?l?l?d?d?d 11,881,376,000 ~20 min 0.24s
?a x 8 6,634,204,312,890,625 ~21 years ~1.5 days

How to read it: three lessons in one table. First, short passwords vanish instantly even on CPU. Second, a GPU changes the units wholesale (minutes→seconds, years→days). Third, even so, "8 characters of everything" takes a GPU a day and a half — and don’t forget this is the story of a fast hash (MD5). With yescrypt, this entire table inflates by tens of thousands of times.

3-6. Checking Results — –show

To see just the results after cracking finishes (screen example):

hashcat -m 0 hash.txt --show
f30aa7a662c728b7407c54ae6bfd27d1:hello123

How to read it: hashcat records cracked hashes in a potfile (a results file), so --show pulls out the stored results without re-cracking. Same idea as Step 123’s john --showeven when the tool changes, the "hash:plaintext" reporting format stays the same.

3-7. Summarizing Mode-Selection Criteria

Here’s how to choose which mode to use first, by situation.

Situation First choice
No information at all -a 0 dictionary (rockyou) — people use words
There’s word of a pattern like "birthday + digits" -a 3 mask, exhausting just that pattern
Signs of two words joined -a 1 combinator
Both dictionary and mask failed Dictionary + rules, or widen the mask — and record "not crackable" as a result in the report

Why: cracking isn’t spinning blindly — it’s a resource-allocation game of exhausting candidates from highest probability to cheapest. The reason a dictionary always comes before a mask — one dictionary run costs seconds, a large mask costs days.


4. Missions & Exercises

Mission — Crack the Same Hash with Two Modes

  1. Make a practice hash with echo -n "test99" | md5sum and save it to a file
  2. Crack it with a dictionary attack in a GPU lab (or a --force CPU environment) — feel free to add test99 to the dictionary yourself
  3. Crack the same hash with a mask attack (?l?l?l?l?d?d) too
  4. Confirm the result with --show, and calculate and record the difference in attempt counts between the two modes
  5. Organize a "mode-selection criteria by situation" table in your wiki

Exercises

Exercise 1. Explain why echo "pass" | md5sum and echo -n "pass" | md5sum give different results.

Exercise 2. Calculate the total attempt count of the mask ?u?l?l?l?l?d?d.

Exercise 3. Explain, from a "cost" perspective, why a dictionary attack is almost always tried before a mask attack.

Exercise 4. For the same 8-character password, an MD5 hash cracks in 1.5 days on GPU while a yescrypt hash is effectively uncrackable. What hash-design factor creates this difference?


5. Model Answers & Completion Criteria

Mission Model Answer

echo -n "test99" | md5sum
# 1d56a580bb00ff669f38e5c1f69b497c  -   (compare with your output — this value is measured)

echo -n "test99" | md5sum | awk '{print $1}' > hash.txt
# dictionary attack: hashcat -m 0 -a 0 hash.txt mydict.txt   (screen example — dict includes test99)
# mask attack: hashcat -m 0 -a 3 hash.txt "?l?l?l?l?d?d"   (screen example)

How to verify: ① did you calculate yourself that the mask ?l?l?l?l?d?d totals 26⁴×10² = 45,697,600 tries? ② does your md5sum result start with 1d56a5… — if not, suspect a missing -n. ③ was the same plaintext recovered in both modes? ④ does your mode-selection table start with "no information → dictionary"?

Exercise Answers

Answer 1. By default echo appends a newline character (n) at the end of its output. A hash is computed over every byte of the input, so the presence of the newline produces a completely different hash (measured in section 3-1: hello123 is f30aa7…, hello123n is 0766c5…).

Answer 2. ?u is 26, four ?l is 26⁴, two ?d is 10² — 26×26⁴×100 = 26⁵×100 = 1,188,137,600 tries. Uppercase start + 4 lowercase + 2 digits is a common password pattern (e.g., Apple01), so it’s a mask you see often in the field.

Answer 3. A dictionary is a collection of passwords people actually used, so the success probability per candidate is overwhelmingly high, and at ~14 million entries it finishes in seconds on GPU. A mask, by contrast, inflates candidates geometrically, so a large mask costs hours to days. "Cheapest and most probable first" is the standard of resource allocation.

Answer 4. A design that deliberately slows computation. MD5 is built to be computed fast, so a GPU can try tens of billions per second, but password-dedicated hashes like yescrypt and bcrypt raise the iteration count and memory requirements so each computation is expensive. When attempt speed falls to thousands per second, the total time of exhaustive trying inflates by tens of thousands of times.

Completion Criteria Checklist

  • [ ] I can make a correct practice hash with echo -n
  • [ ] I know how to find the mode number (-m) for a hash type
  • [ ] I can explain the difference between -a 0 (dictionary) and -a 3 (mask)
  • [ ] I can calculate mask charsets (?l ?u ?d ?a) and attempt counts
  • [ ] I can estimate expected cracking time from combination count and speed
  • [ ] I can check stored results with --show
  • [ ] Mission: I finished cracking with both modes and writing the criteria table

6. Common Pitfalls & Fixes

Wall 1. It won’t crack even though I know the answer

Symptom: hello123 is the answer and it’s in the dictionary, yet Status says Exhausted (tried everything and failed).

Cause: nine times out of ten, a missing -n at hash-creation time — you’re cracking a different value that includes the newline (compare with the measurement in section 3-1).

Fix: check that the target hash is f30aa7a662c728b7407c54ae6bfd27d1. If it starts with 0766c5..., a newline got in. Make it again with echo -n.

Wall 2. "No devices found" or it’s too slow

Symptom (screen example): a No devices found/left error, or the GPU isn’t detected inside a VM.

Cause: most virtual machines can’t use the GPU directly.

Fix: hashcat --force lets you run on CPU — slow, but enough for learning the concepts. This chapter’s purpose is not speed but the mindset of mode selection. Real speed measurement is the job of lab equipment with a GPU.

Wall 3. Format errors like "Hash-mode was not specified"

Symptom (screen example): it fails to recognize the hash right at startup.

Cause: the -m number doesn’t match the hash type. Running sha512crypt ($6$) as -m 0 (MD5) fails on format from the start.

Fix: identify the hash by its shape first — 32 hex digits is an MD5 candidate, starting with $6$ means 1800. Find the number with hashcat --help | grep -i <name>.

Wall 4. I typed the mask without quotes and it behaves strangely

Symptom: hashcat -m 0 -a 3 hash.txt ?l?l?l gets mangled by the shell.

Cause: ? is a shell wildcard, so without quotes the shell interprets it first.

Fix: always wrap masks in quotes — "?l?l?l?l?d?d".

Wall 5. rockyou.txt doesn’t exist

Symptom: /usr/share/wordlists/rockyou.txt is reported missing.

Cause: depending on the distribution, it’s compressed (rockyou.txt.gz) or not included at all.

Fix: if it’s there, decompress with gunzip; if not, make a small dictionary yourself for practice — printf 'hello123ntest99npasswordn' > mydict.txt. For concept practice, a ten-line dictionary is enough.


7. Summary

Today’s Concepts

Concept One-line explanation
GPU cracking Parallelizes candidate submission across thousands of simple compute cores — thousands of times faster than CPU
Hash mode number (-m) The number telling the tool what kind of hash it is (MD5=0, sha512crypt=1800)
Dictionary attack (-a 0) Submits a real leaked word list in order — the cheapest, most probable first move
Combinator attack (-a 1) Generates candidates by joining words from two dictionaries
Mask attack (-a 3) Exhaustively tries by specifying per-position shapes (?l?d, etc.)
Combinatorial explosion Each position multiplies by the charset size — why password length is security

Today’s Commands & Code

Command What it does
echo -n "phrase" | md5sum Make a practice hash without a newline
hashcat -m 0 -a 0 hash dict MD5 dictionary attack (screen example)
hashcat -m 0 -a 3 hash "?l?l?l?l?d?d" MD5 mask attack (screen example)
hashcat -m 0 hash --show View cracked results again (screen example)
26**5 * 10**3 (Python) Calculate a mask’s attempt count (measured)

An Instinct More Important Than Commands

The essence of cracking is not the tool but the design of candidate order. The only way to find an unknown password is to try them all, and the game is decided by "do you submit high-probability candidates first, in cheapest order?" The sequence dictionary → pattern mask → widened range is that design. Now flip the table and read it with a defender’s eyes — the very numbers you calculated today (multiply per character, tens of thousands of times for slow hashes) are the grounds of password policy. The point where an attacker’s spreadsheet becomes a defender’s blueprint — that is the rhythm of this course.


Once every box is checked, Step 124 is complete.