Crack Me If You Can 2026/ DEF CON 34/ Street Division

Reading the usernames.

How team iceberg10 turned one contest hint — "look closer at usernames" — into the key that unlocked the memory-hard scoreboard.

862
Cracks submitted
760
Accepted
1.43M
Points
48h
Fri 11a → Sun 11a PDT
§01

Overview

CMIYC 2026 handed the Street division fourteen hash types — fast unsalted digests, classic salted crypts, memory-hard KDFs, a bespoke custom KDF, and file-based challenges — with plaintexts drawn from eighteen undisclosed "ideas." Our score came almost entirely from decoding one generation rule and applying it to the highest-value memory-hard hashes, backed by disciplined volume work and a data-driven endgame pivot.

Three of the four richest hash types carried ~96% of our points from a handful of cracks. In the Street division, which hashes you crack dwarfs how many.

Hash typePrefixCrackedPts / eaPoints
yescrypt$y$1747,000799,000
argon2id$argon2id$1035,000350,000
bcrypt$2a$08$317,500232,500
sm3crypt$sm3$4450022,000
md5crypt$1$8620017,200
sha512crypt$6$42,0008,000
sha1crypt$sha1$74002,800
openssha{SSHA}3720740
raw-sha3843592718
raw-md52671267
gost_yescrypt$gy$060,0000
cmiyc (custom KDF)$cmiyc$052,5000
scrypt$7$014,0000
§02

How we worked — one human, one agent

Team iceberg10 was two members, and only one of them slept. The split was clean and it played to both sides' strengths: a human commander and an AI operator, trading direction for execution in a tight loop for 48 hours.

Lance Grover

Human · commander & strategist
  • Owned the hardware fleet and the vast.ai budget; made the go/no-go calls and set the cadence.
  • Brought the KoreLogic username hint to the table — the crack that opened everything.
  • Asked the sharp questions: "do rules even help, or should we derive them from what we've cracked?" · "split gost across all boxes in parallel" · "recycle our cracks" · "if a box hasn't produced in an hour, change it."
  • Pointed at the live field-stats page — the best strategic signal of the endgame.
  • Physical ops: rebooting a wedged box, feeding budget, sanity-checking direction.

Claude Code

AI agent · operator, analyst & engineer
  • Built and drove the loop automation — pull, import street-only, submit (GPG+SMTP), parse the autoresponder (IMAP), track in SQLite.
  • Ran the crack analysis that decoded the surname→language rule and built the per-language classifier.
  • Generated the multilingual wordlists and the derived rule set; reverse-engineered the AIX/PowerPC $cmiyc$ hasher.
  • Orchestrated the fleet: dispatch, de-dup, value-weighted rebalancing, the whole vast.ai lifecycle.
  • Caught the traps: the false gost "DES fallback," leaked John forks, the deadline-timezone error.

It settled into a rhythm fast: Lance would ask a question or make a call, Claude would go run with it and come back with a one-line answer, and Lance would decide what came next. Neither of us pulls this off solo — Lance doesn't have the patience for a stripped PowerPC binary at 2 a.m., and Claude doesn't have a vast.ai budget or a gut feeling about which tweet is actually a hint.

§03

The rig

A hybrid of owned iron plus cloud burst, driven by a self-pacing loop.

Local fleet

whitebox (RTX 2060 · 12c), box44 (12c + GPU), cryptorig (6× GTX 1060 · 2c), cpubox (8c), local workstation (GTX 1080 · 12c).

Cloud burst

Up to 4× vast.ai RTX 4090 @ $0.27–0.29/hr, spun up on demand for memory-hard & fast-salted GPU work. Total spend ≈ $17–18 of a $25 budget.

Automation

A /loop: pull potfiles → import street-only → submit → read autoresponder → analyze → dispatch. Later cron'd every 30 min. Cracks in SQLite; GPG+SMTP submit; IMAP autoresponder parse.

Cracking stack

hashcat v7.1.2 for fast & GPU-tractable hashes; John jumbo --format=crypt for yescrypt / gost / scrypt via system libxcrypt; native scrypt; dmg2john.

§04

The master key

The hint

"If you think we haven't given a lot of hints this year, you haven't been looking too closely at usernames."

— KoreLogic, mid-contest

Usernames were finitiallast (first-initial + surname). Cross-referencing our cracks against them revealed the rule that defined our contest:

Each password is the hash-type's theme concept, expressed in the language of the user's surname — plus light transforms (leet, reversal + capitalize).

Confirmed 20-for-20 on bcrypt and across every type. A password we'd never have guessed blind becomes obvious once the surname points to the language:

UsernamePasswordDecode
za·rajputIspawHindi wapsi ("return") — reversed + capitalized
ap·larsenNegiDanish igen ("again") — reversed
mm·gotoUreakJapanese kaeru ("return") — reversed
ie·kozlovsn0vaRussian snova ("again") — leet
af·simsektekr4rTurkish tekrar ("again") — leet
es·michalakisepistrofiGreek "return"
wa·rothlöschenGerman "delete"
mn·yilmazgüvenlikTurkish "security"

Themes ran per hash type

Knowing the language per user let us target each hash with only its surname's language instead of spraying ~40 — an ~200× keyspace cut that made the slow memory-hard types tractable.

§05

Wordlists & rules

Coverage beats rules

Analysis of 636 cracks showed ~half were mangled, but with a small, specific transform set — leet e→3 i→1 o→0 s→5 a→4 t→7 a→@ i→! s→$, capitalize, reverse, single-char suffix. We derived a tight 48-rule set that regenerated 10 of 10 known mangled cracks — leaner and cheaper than AllRules, and safe to run even on salted types.

comeback-expand

"Return/again/comeback" in ~45 languages incl. transliterated Japanese, Chinese, Korean, Hindi, Arabic, Greek — variants baked in.

dataprot-expand

The argon2 GDPR vocabulary: 10 concepts × ~25 languages × variants — with native accented forms (soukromí, löschen).

Two hard rules of thumb: passwords keep native accents, so wordlists must carry accented and ASCII forms; and single-position leet (kurtarm@k — only the 2nd a) can't be done by any global rule and must be baked into the list.

§06

Challenges

Round 2 — the $cmiyc$ custom KDF

The Round-2 bundle decrypted to a stripped AIX / PowerPC (RS/6000 XCOFF32) binary — the reference hasher. Reverse-engineered from PPC traceback tables and disassembly: a scrypt-style memory-hard ROMix over SHA-512 (HMAC-SHA512 seed, N = 2²⁰ 64-byte blocks, mixing rounds, a brainfuck normalization step), format $cmiyc$2026$4$20$salt$hash64 MB and ~5M SHA-512 per guess. Reimplemented and smoke-tested, but at ~18s/guess in Python it needs a C/GPU port to be viable. field cracked: 0 / 635

Challenge 4 — encrypted disk images

Four Apple encrcdsa DMGs, PBKDF2-HMAC-SHA1 at 400k–476k iterations — John --format=dmg, CPU-only, extracted with dmg2john.py. Too slow to brute at scale in the time remaining.

§07

Gotchas from the trenches

§08

The endgame pivot

KoreLogic's live password-info page published field-wide crack counts per type — an opportunity map. It showed argon2id was the most-crackable high-value type (field 5.5%) while we'd barely touched it, and gost was 0.3% (we were over-invested there). We chased the gap on argon2 with a deeper GDPR wordlist — but our themes couldn't match most of the field's argon2 ideas, so we did the harder thing: accepted that realized EV beats theoretical EV and re-pointed the 4090s to fast-salted field gaps that actually produced. A late loopback / recycle sweep — every cracked plaintext × derived-rules against the other types — mopped up cross-type password reuse.

The last real save wasn't a crack — it was catching that the deadline was 11:00 AM PDT, one hour earlier than a mis-set teardown assumed. Verifying the true end time preserved the final submit and stopped the cloud boxes billing past the finish.

§09

Lessons for the Street division

  1. Never submit Pro hashes as Street. They return invalid — our only 83 invalids were early, before we hard-filtered to street-only.
  2. Read the usernames. The single biggest lever was decoding the surname→language rule.
  3. Themes are per hash type. Analyze cracks grouped by type, never in aggregate.
  4. Coverage > rules. Bake variants into the wordlist; derive a tight rule set from your own cracks.
  5. Value-weight every box. One yescrypt (47k) outweighs thousands of raw-md5. Points-per-crack should drive allocation.
  6. The field-stats page is a map. Chase provably-crackable gaps where value is high.
  7. Verify the deadline timezone and pre-schedule the final submit + cloud teardown.
§10

The toolkit

The scripts we built are open-sourced in tools/ — sanitized and ready to adapt.

Methodology

run as-is
  • target-by-surname.pythe star: surname→language classifier + per-language targeting. The master key (§04) as an attack — a ~200× keyspace cut on the slow types.
  • comeback-expand.py — multilingual return/comeback wordlist (~45 languages, variants baked in).
  • dataprot-expand.py — the argon2 GDPR wordlist, accented native forms included.
  • derived-theme.rule — the 48-rule set derived from our own cracks (hashcat + John).
  • cmiyc_hash.py + RE notes — the reverse-engineered $cmiyc$ KDF.

Orchestration

sanitized templates
  • loop-submit.sh — pull fleet pots → import street-only → submit pending. The street-filter is the point.
  • loop-cron.sh — the endgame ~30-min auto-loop, incl. the wordlist-split-across-boxes pull.
  • checkresp.py — parses the autoresponder over IMAP for accepted / invalid counts per submission.

Cloud burst · vast-*.sh

On-demand RTX 4090 rental. The gold is vast-lib.sh's onstart: install the hashcat v7.1.2 binary (apt's v6.2 CUDA backend dies on modern vast drivers) and the critical libnvrtc.so symlink fix — the runtime image ships only libnvrtc.so.12 but hashcat opens the plain name, so without it you get a silent 1000×-slower CPU fallback. Readiness is benchmark-gated (GH/s, not MH/s) so you never dispatch to a dead box. Plus up / status / crack / down for the full rent → run → teardown lifecycle.

The one worth stealing is target-by-surname.py — the whole username-hint idea, made concrete. Everything else is supporting cast.