Password Cracking and Wordlist Engineering Part 2: Hashcat Fundamentals and the GPU Economics of Cracking
Part 1 laid out the hash landscape this series works through and why offline cracking has no rate limit but the hardware. This post puts a number on “the hardware” — verified flag syntax against a real hashcat install, and real, sourced GPU throughput figures for the exact formats Part 3 and Part 4 of the Impacket series produced.
Verifying the tool before trusting anything it’s said to do
Every command in this series is checked against an actual install rather than copied from memory or an old cheat sheet — the same standard the Impacket series held itself to. hashcat ships as a portable, self-contained release; no package manager needed:
$ ./hashcat.bin --version
v6.2.6
The core syntax is one line, three parts:
hashcat [options] <hash|hashfile> [dictionary|mask|directory]
-m picks the hash type (the mode numbers from Part 1’s table), -a picks the attack mode — the strategy for generating candidate passwords, independent of which hash you’re targeting. That second axis is what this post is really about.
The five attack modes
hashcat separates “what hash” from “how to guess” cleanly, and the -a flag is the whole of the second question:
-a | Name | What it does |
|---|---|---|
0 | Straight | Try each line of a wordlist as-is (or with -r rules.txt applied — Part 5) |
1 | Combinator | Concatenate every word in list A with every word in list B |
3 | Brute-force / mask | Generate candidates from a character-position pattern (Part 6) |
6 | Hybrid wordlist + mask | Append a mask to every wordlist entry (password + ?d?d?d?d → password0000…password9999) |
7 | Hybrid mask + mask | Prepend a mask to every wordlist entry |
Mode 0 is the workhorse and the one this post’s numbers assume — a wordlist, optionally mutated by rules, tried straight against the target hash:
$ hashcat -m 13100 -a 0 spns.txt rockyou.txt
That’s the literal command Part 9 of the Impacket series ran to turn svc-backup’s Kerberoasted ticket into B4ckup$SQL2024 — mode 13100 for the hash type, mode 0 for “just try the wordlist.”
Real throughput, not hand-waving
Every GPU cracking number that gets repeated online eventually traces back to someone’s actual benchmark run. Rather than restate a figure from memory, here’s a published, attributable one: a hashcat v6.2.6 benchmark on an NVIDIA RTX 4090 at stock clocks, run by a known contributor to the hashcat community and posted publicly for exactly this kind of citation.
| Hash-Mode | Format | Speed (RTX 4090, hashcat v6.2.6) |
|---|---|---|
| 1000 | NTLM | 288.5 GH/s |
| 13100 | Kerberos 5, etype 23, TGS-REP (Kerberoast) | 3,478.0 MH/s |
| 18200 | Kerberos 5, etype 23, AS-REP | 3,564.1 MH/s |
| 3200 | bcrypt $2*$, cost factor 5 | 184.0 kH/s |
Source: Chick3nman’s published RTX 4090 hashcat v6.2.6 benchmark.
The gap between the top row and the bottom row is the entire argument of this series’ defensive half, stated as a single number: NTLM cracks roughly 1.5 million times faster than bcrypt at cost 5 on identical hardware. Kerberoasting and AS-REP sit closer to bcrypt than to NTLM — RC4-HMAC and the SPN-derived salt cost real throughput compared to raw NTLM — but they’re still roughly 19,000× faster than bcrypt. That difference isn’t a rounding error in a benchmark table; it’s the difference between “cracked before the coffee’s done” and “not cracked in this lifetime,” for candidate sets of identical size.
To make that concrete: rockyou.txt is 14,344,391 unique passwords. At NTLM’s 288.5 GH/s, testing every single one takes about 50 microseconds — the wordlist size stops mattering entirely; the bottleneck becomes generating candidates faster than the GPU can hash them, which is exactly why Parts 5 and 6 exist (rules and masks generate far more candidates than any static wordlist file could hold). At Kerberoast’s 3.48 GH/s, the same 14.3 million candidates take about 4 milliseconds — still nothing. Full rockyou against any format in this table is a non-event; it’s the keyspace beyond rockyou — rules, masks, combinator attacks — where these formats actually diverge from each other.
An 8-character full-charset brute-force (?a?a?a?a?a?a?a?a, all 95 printable ASCII characters, -a 3) is a fairer stress test — 95^8 ≈ 6.63 × 10^15 candidates:
| Format | Time to exhaust ?a?a?a?a?a?a?a?a on one RTX 4090 |
|---|---|
| NTLM (1000) | ~6.4 hours |
| Kerberoast (13100) | ~22 days |
| bcrypt cost 5 (3200) | ~1,140 years |
That bcrypt row is doing real work: bcrypt’s cost factor is a tunable log2 round count, and going from cost 5 (this benchmark) to cost 10 (a realistic production setting) costs roughly another 32× — pushing that exhaustive search from “over a millennium” to a number with no practical meaning at all. Part 8 comes back to this exact table with Argon2 and scrypt added, because this economics argument is the entire case for choosing a slow KDF over a fast one.
What that throughput actually costs to rent
An RTX 4090 isn’t hypothetical hardware — it’s rentable, on-demand, for less than a coffee: spot/interruptible listings on GPU marketplaces run roughly $0.29–$0.35/hour as of mid-2026, on-demand non-interruptible listings somewhat more.
At $0.30/hour, exhausting that entire 8-character NTLM keyspace (~6.4 hours) costs about $1.92 — genuinely trivial, and this is a single rented GPU; nothing here assumes a cluster. That’s the actual, unglamorous economic case for treating every NTLM hash as already compromised the moment it’s exfiltrated: the barrier to brute-forcing it isn’t cost or access, it’s remembering the mode number.
The Kerberoast row tells a different story economically, and it’s worth sitting with: ~22 days of GPU time at $0.30/hour is roughly $158 — not nothing, but well within reach of anyone motivated, and that’s exhaustive brute force against the entire keyspace with zero intelligence applied. Nobody exhausts a keyspace blind when a targeted wordlist and rule set (Parts 4 and 5) can find a real human-chosen password in a fraction of that time, at a fraction of that cost. The brute-force numbers above are the ceiling, not the typical case — Part 7’s actual crack of svc-backup’s Kerberoast hash took under a second, because B4ckup$SQL2024 was a wordlist-plus-rule hit, not a brute-force one.
Verifying a crack, not just running one
Once hashcat finds a match, two flags matter for actually using the result. --show re-displays already-cracked hashes from the potfile without re-running the attack:
$ hashcat -m 13100 --show spns.txt
$krb5tgs$23$*svc-backup$CONTOSO.LOCAL$MSSQLSvc/FS01.CONTOSO.LOCAL~1433*$...:B4ckup$SQL2024
And -o outfile.txt writes results to a file in a chosen format as they’re found, useful for feeding straight into a report or the next stage of an assessment — verified directly against the installed binary’s --help output, not assumed from an older hashcat version where the flag set has genuinely changed release to release.
Where this leaves the series
Part 1 established what’s crackable and why offline cracking is unbounded. This post put a real number on “unbounded” for the fast-hash formats this series cares about most — NTLM, Kerberoast, AS-REP — and showed the same GPU turns into a wall the moment the hash function is deliberately slow. Part 3 covers the other major cracking tool, John the Ripper, and a distinction that turned out to matter more in practice than expected: the version apt install john gives you is not the version most Kerberoast/AS-REP tutorials assume you have.