Skip to main content

Class Definition

class HashCracker:
    """Crackeo rápido de hashes MD5 con diccionario"""
Fast MD5 hash cracker that uses a precomputed hash dictionary and common password list to crack credential hashes.

Class Attributes

HASH_MD5_KNOWN

Precomputed dictionary of known MD5 hashes and their plaintext passwords.
HASH_MD5_KNOWN = {
    '5f4dcc3b5aa765d61d8327deb882cf99': 'password',
    '21232f297a57a5a743894a0e4a801fc3': 'admin',
    '0192023a7bbd73250516f069df18b500': 'admin123',
    'e10adc3949ba59abbe56e057f20f883e': '123456',
    '63a9f0ea7bb98050796b649e85481845': 'root',
    '7813d1590d28a7dd372ad54b5d29571b': 'toor',
    '0d107d09f5bbe40cade3de5c71e9e9b7': 'letmein',
    '40be4e59b9a2a2b5dffb918c0e86b3d7': 'monkey',
    '8621ffdbc5698829397d97767ac13db3': 'dragon',
    'eb0a191797624dd3a48fa681d3061212': 'qwerty',
    'd8578edf8458ce06fbc5bb76a58c5ca4': 'qwerty',
}
Usage: Instant lookup table for common passwords without requiring computation.

Class Methods

crack_md5(hash_value)

Attempts to crack a single MD5 hash using known hashes and common passwords.
@classmethod
def crack_md5(cls, hash_value: str) -> str | None
hash_value
str
required
MD5 hash string (32 hexadecimal characters)
return
str | None
Plaintext password if cracked, None if unable to crack
Cracking Strategy: 1. Known Hash Lookup (Instant)
hash_lower = hash_value.strip().lower()
if hash_lower in cls.HASH_MD5_KNOWN:
    return cls.HASH_MD5_KNOWN[hash_lower]
2. Common Password Brute-Force
for pwd in Config.COMMON_PASSWORDS:
    if hashlib.md5(pwd.encode()).hexdigest() == hash_lower:
        return pwd
Example:
# Known hash lookup
cracked = HashCracker.crack_md5('5f4dcc3b5aa765d61d8327deb882cf99')
print(cracked)  # 'password'

# Common password computation
cracked = HashCracker.crack_md5('482c811da5d5b4bc6d497ffa98491e38')
print(cracked)  # 'password123' (if in Config.COMMON_PASSWORDS)

# Unable to crack
cracked = HashCracker.crack_md5('abcd1234567890abcdef1234567890ab')
print(cracked)  # None
Performance:
  • Known hash lookup: O(1) - Instant
  • Common password check: O(n) - Depends on Config.COMMON_PASSWORDS size

crack_credentials(credentials)

Cracks all MD5 hashes in a list of credential dictionaries.
@classmethod
def crack_credentials(cls, credentials: list[dict]) -> int
credentials
list[dict]
required
List of credential dictionaries, each containing:
  • user (str): Username
  • hash (str): MD5 hash to crack
  • password (str): Will be updated with cracked password
  • cracked (bool): Will be set to True/False
return
int
Number of hashes successfully cracked
Process:
  1. Validates hash format (32 hexadecimal characters)
  2. Attempts to crack using crack_md5()
  3. Updates credential dictionary in-place
  4. Displays results with rich console output
Example:
credentials = [
    {'user': 'admin', 'hash': '5f4dcc3b5aa765d61d8327deb882cf99', 'password': '', 'cracked': False},
    {'user': 'user1', 'hash': 'e10adc3949ba59abbe56e057f20f883e', 'password': '', 'cracked': False},
    {'user': 'user2', 'hash': 'unknown_hash_12345678901234567890', 'password': '', 'cracked': False}
]

cracked_count = HashCracker.crack_credentials(credentials)
print(f"Cracked {cracked_count} out of {len(credentials)} hashes")

# credentials is now:
# [
#   {'user': 'admin', 'hash': '5f4d...', 'password': 'password', 'cracked': True},
#   {'user': 'user1', 'hash': 'e10a...', 'password': '123456', 'cracked': True},
#   {'user': 'user2', 'hash': 'unkn...', 'password': '', 'cracked': False}
# ]
Console Output:
✅ CRACKED: admin → 5f4dcc3b5aa765d6... = 'password'
✅ CRACKED: user1 → e10adc3949ba59ab... = '123456'
❌ No crackeado: user2 → unknown_hash_1234...

Hash Validation

MD5 Format Validation:
if hash_val and len(hash_val) == 32 and all(c in '0123456789abcdefABCDEF' for c in hash_val):
    # Valid MD5 hash
    result = cls.crack_md5(hash_val)
Validated Criteria:
  • Hash exists (not empty)
  • Exactly 32 characters
  • Only hexadecimal characters (0-9, a-f, A-F)

Integration with SQLMapInjector

Typical Usage Flow:
# 1. SQLMapInjector extracts hashed credentials
injector = SQLMapInjector(host)
vulns = injector.attack()
# host.credentials now contains MD5 hashes

# 2. HashCracker attempts to crack them
from services.hash_cracker import HashCracker
cracked_count = HashCracker.crack_credentials(host.credentials)

# 3. Credentials now contain plaintext passwords where possible
for cred in host.credentials:
    if cred['cracked']:
        print(f"{cred['user']}:{cred['password']}")

Common Passwords Configuration

From Config.COMMON_PASSWORDS:
COMMON_PASSWORDS = [
    'password', 'admin', '123456', 'password123',
    'root', 'toor', 'letmein', 'admin123',
    'qwerty', 'monkey', 'dragon', '12345678',
    # ... potentially hundreds more
]
Performance Consideration: For each unknown hash, all passwords in this list are hashed and compared. Longer lists increase coverage but reduce speed.

Credential Dictionary Structure

Input Format:
{
    'source': 'SQLMap (DVWA)',      # Where credential was found
    'user': 'admin',                # Username
    'password': '5f4dcc3b...',      # MD5 hash (before cracking)
    'hash': '5f4dcc3b...',          # Original hash (preserved)
    'cracked': False                # Cracking status
}
After Cracking:
{
    'source': 'SQLMap (DVWA)',
    'user': 'admin',
    'password': 'password',         # Cracked plaintext
    'hash': '5f4dcc3b...',          # Original hash preserved
    'cracked': True                 # Successfully cracked
}

Output Formatting

Success Output:
rprint(f"   [bold green]✅ CRACKED: {cred['user']}{hash_val[:16]}... = '{result}'[/bold green]")
Example:
✅ CRACKED: admin → 5f4dcc3b5aa765d6... = 'password'
Failure Output:
rprint(f"   [yellow]❌ No crackeado: {cred['user']}{hash_val[:16]}...[/yellow]")
Example:
❌ No crackeado: user2 → ab12cd34ef56gh78...

Limitations

Current Limitations:
  1. MD5 Only: Does not support other hash types (SHA-1, SHA-256, bcrypt, etc.)
  2. Small Dictionary: Limited to HASH_MD5_KNOWN + Config.COMMON_PASSWORDS
  3. No Rainbow Tables: Does not use precomputed rainbow tables
  4. No External Tools: Does not integrate with tools like John the Ripper or Hashcat
Recommended External Tool: For stronger hash cracking, use Hashcat:
hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt

Hash Computing Example

How to Add New Hashes:
import hashlib

password = "mypassword"
hash_md5 = hashlib.md5(password.encode()).hexdigest()
print(f"'{hash_md5}': '{password}',")  # Add to HASH_MD5_KNOWN
Output:
'34819d7beeabb9260a5c854bc85b3e44': 'mypassword',

Dependencies

  • hashlib: MD5 hash computation
  • config.Config: Common passwords list
  • rich.print: Formatted console output

Build docs developers (and LLMs) love