Claude Code Plugins

Community-maintained marketplace

Feedback

Crack password hashes using dictionary attacks, rainbow tables, and hashcat. Use this skill when recovering passwords from hashes, identifying hash types, or exploiting weak password policies in CTF challenges.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name hash-cracking
description Crack password hashes using dictionary attacks, rainbow tables, and hashcat. Use this skill when recovering passwords from hashes, identifying hash types, or exploiting weak password policies in CTF challenges.

Hash Cracking

Identify and crack password hashes.

Hash Type Identification

import re

def identify_hash(hash_str: str) -> list:
    """Identify possible hash types based on format and length."""
    hash_str = hash_str.strip()
    possibilities = []

    # Length-based identification
    length = len(hash_str)

    if length == 32 and re.match(r'^[a-fA-F0-9]+$', hash_str):
        possibilities.extend(['MD5', 'MD4', 'NTLM', 'LM'])

    elif length == 40 and re.match(r'^[a-fA-F0-9]+$', hash_str):
        possibilities.extend(['SHA1', 'MySQL5'])

    elif length == 64 and re.match(r'^[a-fA-F0-9]+$', hash_str):
        possibilities.extend(['SHA256', 'SHA3-256', 'BLAKE2s'])

    elif length == 128 and re.match(r'^[a-fA-F0-9]+$', hash_str):
        possibilities.extend(['SHA512', 'SHA3-512', 'BLAKE2b', 'Whirlpool'])

    # Format-based identification
    if hash_str.startswith('$1$'):
        possibilities.append('MD5-Crypt')
    elif hash_str.startswith('$2a$') or hash_str.startswith('$2b$'):
        possibilities.append('Bcrypt')
    elif hash_str.startswith('$5$'):
        possibilities.append('SHA256-Crypt')
    elif hash_str.startswith('$6$'):
        possibilities.append('SHA512-Crypt')
    elif hash_str.startswith('$argon2'):
        possibilities.append('Argon2')
    elif ':' in hash_str:
        possibilities.append('Hash:Salt format')

    return possibilities

# Example
test_hash = "5d41402abc4b2a76b9719d911017c592"
print(identify_hash(test_hash))  # ['MD5', ...]

Common Hash Functions

import hashlib

def compute_hash(data: str, algorithm: str = 'md5') -> str:
    """Compute hash of string."""
    h = hashlib.new(algorithm)
    h.update(data.encode())
    return h.hexdigest()

def compute_all_hashes(data: str) -> dict:
    """Compute all common hashes."""
    algorithms = ['md5', 'sha1', 'sha256', 'sha512', 'sha3_256']
    return {algo: compute_hash(data, algo) for algo in algorithms}

# Example
password = "password123"
hashes = compute_all_hashes(password)
for algo, h in hashes.items():
    print(f"{algo}: {h}")

Dictionary Attack

import hashlib

def dictionary_attack(target_hash: str, wordlist_path: str, algorithm: str = 'md5') -> str:
    """Crack hash using dictionary attack."""
    with open(wordlist_path, 'r', encoding='latin-1') as f:
        for line in f:
            word = line.strip()
            h = hashlib.new(algorithm)
            h.update(word.encode())
            if h.hexdigest() == target_hash.lower():
                return word
    return None

def dictionary_attack_with_rules(target_hash: str, wordlist_path: str, algorithm: str = 'md5') -> str:
    """Dictionary attack with common mutations."""
    rules = [
        lambda x: x,
        lambda x: x.upper(),
        lambda x: x.capitalize(),
        lambda x: x + '1',
        lambda x: x + '123',
        lambda x: x + '!',
        lambda x: x.replace('a', '@'),
        lambda x: x.replace('e', '3'),
        lambda x: x.replace('o', '0'),
        lambda x: x[::-1],
    ]

    with open(wordlist_path, 'r', encoding='latin-1') as f:
        for line in f:
            word = line.strip()
            for rule in rules:
                try:
                    mutated = rule(word)
                    h = hashlib.new(algorithm)
                    h.update(mutated.encode())
                    if h.hexdigest() == target_hash.lower():
                        return mutated
                except:
                    continue
    return None

# Example
target = "5f4dcc3b5aa765d61d8327deb882cf99"  # MD5 of "password"
# result = dictionary_attack(target, "/usr/share/wordlists/rockyou.txt")

Brute Force Attack

import itertools
import string

def brute_force(target_hash: str, max_length: int = 6, charset: str = None, algorithm: str = 'md5') -> str:
    """Brute force hash with character set."""
    if charset is None:
        charset = string.ascii_lowercase + string.digits

    for length in range(1, max_length + 1):
        for combo in itertools.product(charset, repeat=length):
            candidate = ''.join(combo)
            h = hashlib.new(algorithm)
            h.update(candidate.encode())
            if h.hexdigest() == target_hash.lower():
                return candidate

    return None

# Example (small charset for demo)
target = "900150983cd24fb0d6963f7d28e17f72"  # MD5 of "abc"
result = brute_force(target, max_length=4, charset="abc")
print(f"Cracked: {result}")

Hash Extension Attack (Length Extension)

import struct

def md5_padding(message_len: int) -> bytes:
    """Generate MD5 padding for length extension attack."""
    padding = b'\x80'
    padding += b'\x00' * ((55 - message_len) % 64)
    padding += struct.pack('<Q', message_len * 8)
    return padding

def sha1_padding(message_len: int) -> bytes:
    """Generate SHA1 padding for length extension attack."""
    padding = b'\x80'
    padding += b'\x00' * ((55 - message_len) % 64)
    padding += struct.pack('>Q', message_len * 8)
    return padding

# Length extension attack concept:
# If you have H(secret || message), you can compute
# H(secret || message || padding || extension) without knowing secret

def length_extension_attack(original_hash: str, original_msg: bytes,
                           secret_len: int, extension: bytes) -> tuple:
    """Perform length extension attack on MD5.

    Returns (new_message, new_hash)
    """
    # This requires implementing MD5 with custom initial state
    # Use hashpumpy library for actual implementation
    pass

Hashcat Integration

import subprocess
import tempfile
import os

def crack_with_hashcat(hash_file: str, wordlist: str, hash_type: int) -> str:
    """Crack hash using hashcat.

    Common hash types:
    - 0: MD5
    - 100: SHA1
    - 1400: SHA256
    - 1800: SHA512
    - 3200: bcrypt
    - 1000: NTLM
    """
    cmd = [
        'hashcat',
        '-m', str(hash_type),
        '-a', '0',  # Dictionary attack
        hash_file,
        wordlist,
        '--quiet',
        '--potfile-disable'
    ]

    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.stdout

# Example hashcat command lines
hashcat_examples = """
# MD5 dictionary attack
hashcat -m 0 hashes.txt wordlist.txt

# MD5 with rules
hashcat -m 0 hashes.txt wordlist.txt -r rules/best64.rule

# SHA256 brute force (6 chars, lowercase + digits)
hashcat -m 1400 hash.txt -a 3 ?l?l?l?l?l?l

# Bcrypt with wordlist
hashcat -m 3200 hash.txt wordlist.txt

# Show cracked hashes
hashcat -m 0 hashes.txt --show
"""

Rainbow Table Lookup

import requests

def online_hash_lookup(hash_str: str) -> str:
    """Look up hash in online rainbow tables."""
    # Example using md5decrypt API
    try:
        # Note: This is conceptual - actual APIs vary
        response = requests.get(f"https://api.example.com/hash/{hash_str}")
        if response.status_code == 200:
            return response.json().get('plaintext')
    except:
        pass
    return None

def check_crackstation(hash_str: str) -> str:
    """Check hash against CrackStation (conceptual)."""
    # CrackStation has web interface, not API
    # Use their website or local rainbow tables
    pass

# Pre-computed common password hashes for quick lookup
COMMON_HASHES = {
    '5f4dcc3b5aa765d61d8327deb882cf99': 'password',
    'e99a18c428cb38d5f260853678922e03': 'abc123',
    'd8578edf8458ce06fbc5bb76a58c5ca4': 'qwerty',
    '25d55ad283aa400af464c76d713c07ad': '12345678',
    '827ccb0eea8a706c4c34a16891f84e7b': '12345',
}

def quick_lookup(hash_str: str) -> str:
    """Quick lookup in common hashes."""
    return COMMON_HASHES.get(hash_str.lower())