hashcrack picoCTF 2025 Solution

Published: April 2, 2025

Description

A breached server challenges you to identify progressively stronger hashes (MD5, SHA-1, SHA-256). Crack each password to reveal the flag.

Connect via nc verbal-sleep.picoctf.net <PORT_FROM_INSTANCE>.

Each prompt prints a hash; identify it by hex length (32 chars = MD5, 40 = SHA-1, 64 = SHA-256), then supply the matching cleartext.

bash
nc verbal-sleep.picoctf.net <PORT_FROM_INSTANCE>
bash
# Three quick ID tricks: hex length, hashid <hash>, or paste into CrackStation
bash
hashid 482c811da5d5b4bc6d497ffa98491e38

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
Three rounds, three hash families. The Hash Cracking guide walks through identifying hash modes by digest length and picking the right hashcat -m value.
  1. Step 1
    Crack the MD5 hash
    Observation
    I noticed the server printed a 32-character hex digest, which is the exact output length of MD5, and that the password 'password123' is one of the most common entries in rockyou.txt, suggesting a straightforward wordlist attack or rainbow table lookup would resolve it instantly.
    32 hex chars means MD5. Paste it into CrackStation or run hashcat against rockyou.txt; either way it resolves to password123.
    bash
    # Option A: CrackStation (web). Option B: hashcat locally.
    bash
    echo '482c811da5d5b4bc6d497ffa98491e38' > h.txt
    bash
    hashcat -m 0 -a 0 h.txt /usr/share/wordlists/rockyou.txt
    bash
    hashcat -m 0 h.txt --show

    Expected output

    482c811da5d5b4bc6d497ffa98491e38:password123
    What didn't work first

    Tried: Running hashcat with mode -m 100 (SHA-1) instead of -m 0 (MD5) because the hash looked long.

    hashcat will report 'Token length exception' or simply return no candidates because it treats the 32-character hex string as an invalid SHA-1 input. MD5 produces a 128-bit (32 hex character) digest while SHA-1 is 160-bit (40 hex characters). Always count the digest length before choosing a mode.

    Tried: Using john instead of hashcat and letting it auto-detect the format, only to get no cracked output.

    John the Ripper's auto-detect can misidentify raw MD5 hashes if they are supplied without a username prefix (the format john expects is 'user:hash'). Explicitly pass --format=raw-md5 to force the right algorithm and avoid silent misidentification.

    Learn more

    MD5 (Message Digest 5) was designed in 1991 as a cryptographic hash function producing a 128-bit (32 hex character) digest. It was considered secure for its time, but researchers began finding practical collision attacks in the early 2000s, and by 2008 it was considered completely broken for security purposes.

    The hash 482c811da5d5b4bc6d497ffa98491e38 corresponds to "password123" - one of the most common passwords ever used. Sites like CrackStation maintain massive precomputed rainbow tables mapping billions of known inputs to their MD5 digests, making lookups instant. This is why MD5 should never be used to store passwords.

    Despite being broken, MD5 is still widely found in legacy systems, file integrity checks (where collision resistance matters less than speed), and CTF challenges. Modern alternatives include bcrypt, scrypt, Argon2, or at minimum SHA-256 with a unique per-user salt to defeat rainbow table attacks.

  2. Step 2
    Crack the SHA-1 hash
    Observation
    I noticed the next hash printed by the server was 40 hex characters long, which uniquely identifies the SHA-1 family (160-bit output), so I switched hashcat to mode -m 100 to match.
    40 hex chars points to SHA-1. Same workflow with mode -m 100 cracks it to letmein against rockyou.
    bash
    echo 'b7a875fc1ea228b9061041b7cec4bd3c52ab3ce3' > h.txt
    bash
    hashcat -m 100 -a 0 h.txt /usr/share/wordlists/rockyou.txt

    Expected output

    b7a875fc1ea228b9061041b7cec4bd3c52ab3ce3:letmein
    What didn't work first

    Tried: Using hashcat mode -m 0 (MD5) on the SHA-1 hash because it worked for the previous step.

    hashcat returns 'Token length exception' because a 40-character hex digest does not match MD5's expected 32 characters. The mode must match the digest family - use -m 100 for raw SHA-1. Reusing the previous mode without checking the digest length is the most common sequencing mistake in multi-round hash challenges.

    Tried: Searching CrackStation for SHA-1 hashes but supplying the raw bytes instead of the lowercase hex string.

    CrackStation and most online lookup tools expect the hash as a lowercase hexadecimal string exactly as printed by the server. Pasting the raw binary bytes or an uppercase hex string often returns no match even though the precomputed entry exists in the database.

    Learn more

    SHA-1 (Secure Hash Algorithm 1) produces a 160-bit (40 hex character) digest. It was the government standard for decades and is far more common in the wild than MD5 - SSL certificates, Git commits, and SVN repositories all historically relied on it.

    Google demonstrated a practical SHA-1 collision in 2017 (the SHAttered attack), definitively ending SHA-1's use in security-critical contexts. The hash above maps to "letmein," another entry in every common wordlist. Because SHA-1 lacks a salt, the same password always produces the same hash, making wordlist attacks trivially fast even without rainbow tables.

    Git still uses SHA-1 internally for object addressing (though the collision risk in that context is considered low), and many older X.509 certificate chains include SHA-1 signatures that browsers now reject. NIST deprecated SHA-1 for most uses in 2011 and fully disallowed it in federal systems by 2014.

  3. Step 3
    Crack the SHA-256 hash
    Observation
    I noticed the final hash was 64 hex characters, which corresponds to SHA-256's 256-bit output, and that the challenge uses weak common passwords throughout, so rockyou.txt with hashcat mode -m 1400 was the natural next step.
    64 hex chars is SHA-256, mode -m 1400. Run it against rockyou.txt (or paste it into CrackStation) to recover the cleartext (qwerty098), then send each cracked password back over the same nc session and the server prints the flag.
    bash
    echo '916e8c4f79b25028c9e467f1eb8eee6d6bbdff965f9928310ad30a8d88697745' > h.txt
    bash
    hashcat -m 1400 -a 0 h.txt /usr/share/wordlists/rockyou.txt

    Expected output

    916e8c4f79b25028c9e467f1eb8eee6d6bbdff965f9928310ad30a8d88697745:qwerty098
    picoCTF{UseStr0nG_h@shEs_&PaSswDs!_7f29...}
    What didn't work first

    Tried: Using hashcat mode -m 1400 but pointing it at a short custom wordlist instead of rockyou.txt, finding no match.

    SHA-256 is computationally fast for a GPU but the cleartext must actually appear in the wordlist. 'qwerty098' is present in rockyou.txt but not in smaller curated lists. Always exhaust the full rockyou.txt (14 million entries) before concluding the hash is uncrackable or switching to brute-force mask attacks.

    Tried: Assuming the SHA-256 hash is salted and adding a salt flag (-m 20400 or similar) when the hash refuses to crack.

    This challenge sends raw unsalted SHA-256 hashes. Adding a salt argument with no separator tells hashcat to expect a different token format, causing 'Token length exception' or zero candidates. Salted hashes appear with a separator character (e.g. 'hash:salt') - a bare 64-character hex string with no colon is always unsalted raw SHA-256.

    Learn more

    SHA-256 belongs to the SHA-2 family and produces a 256-bit (64 hex character) digest. No practical collision has ever been found, and it remains the backbone of TLS, Bitcoin, code signing, and many password storage schemes. However, SHA-256 alone is not safe for passwords.

    The issue is speed: modern GPUs can compute billions of SHA-256 hashes per second. When the underlying password is a common one that appears in wordlists like rockyou.txt or SecLists, even a SHA-256 hash of it falls instantly. Secure password hashing requires a slow, memory-hard function like Argon2id, bcrypt, or scrypt, combined with a unique random salt stored alongside the hash.

    This three-step challenge illustrates a key lesson: algorithm strength is irrelevant when users choose weak passwords. A password manager generating random 20-character strings defeats all dictionary attacks regardless of which hash function the server uses. NIST's SP 800-63B now recommends checking passwords against known breach lists rather than enforcing complexity rules.

Interactive tools
  • Hash IdentifierIdentify unknown hash types by length and prefix. Covers MD5, SHA-1, SHA-256, SHA-512, bcrypt, NTLM, and more.
Alternate Solution

Not sure what kind of hash you are looking at? Paste it into the Hash Identifier on this site to confirm whether it is MD5, SHA-1, or SHA-256 before looking it up. For cracking, CrackStation.net covers all three hash types used in this challenge and returns results instantly for common passwords like these.

Flag

Reveal flag

picoCTF{UseStr0nG_h@shEs_&PaSswDs!_7f29...}

Online hash databases crack these instantly, demonstrating why weak hashes are dangerous.

Key takeaway

Hash digests can be identified by length, MD5 at 32 hex characters, SHA-1 at 40, SHA-256 at 64, which tells you the right cracking mode before you start. Fast general-purpose hashes like SHA-256 give weak passwords no protection because a GPU computes billions per second and any password in a wordlist like rockyou.txt falls instantly. Secure password storage requires a slow, memory-hard function such as Argon2id, bcrypt, or scrypt with a unique random salt, since algorithm strength is irrelevant when the underlying password is guessable.

Related reading

Want more picoCTF 2025 writeups?

Tools used in this challenge

Do these first

What to try next