yaklang/hack-skills1 file

Hash Attack Techniques

>-

Specification
Skill ID
yaklang/hack-skills/hash-attack-techniques
Publisher
yaklang
Repository
hack-skills
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

yaklang/hack-skills/hash-attack-techniquesInstalls these files
  • SKILL.md

What this skill tells the agent

SKILL: Hash Attack Techniques — Expert Cryptanalysis Playbook

AI LOAD INSTRUCTION: Expert hash attack techniques for CTF and security assessments. Covers length extension attacks, MD5/SHA1 collision generation, meet-in-the-middle hash attacks, HMAC timing side channels, birthday attacks, and proof-of-work solving. Base models often incorrectly apply length extension to HMAC or SHA-3, or fail to distinguish between identical-prefix and chosen-prefix collisions.

0. RELATED ROUTING

  • rsa-attack-techniques when hash weaknesses affect RSA signature schemes
  • symmetric-cipher-attacks when hash is used in key derivation
  • classical-cipher-analysis when analyzing hash-like constructions in classical ciphers

Quick attack selection

ScenarioAttackTool
`H(secret \\msg)` known, extend messageLength extensionHashPump, hash_extender
Need two files with same MD5Identical-prefix collisionfastcoll
Need specific MD5 prefix matchChosen-prefix collisionhashclash
Byte-by-byte HMAC comparisonTiming attackCustom script
Find any collisionBirthday attackO(2^(n/2))
Proof of work: find hash with leading zerosBrute forcehashcat, Python

1. LENGTH EXTENSION ATTACK

1.1 Vulnerable vs Non-Vulnerable

HashVulnerableWhy
MD5YesMerkle-Damgard construction
SHA-1YesMerkle-Damgard construction
SHA-256YesMerkle-Damgard construction
SHA-512YesMerkle-Damgard construction
SHA-3 / KeccakNoSponge construction
HMAC-*NoDouble hashing prevents extension
SHA-256 truncatedNo (if truncated)Missing internal state bits
BLAKE2NoDifferent construction

1.2 Attack Mechanism

Given:   MAC = H(secret || original_message)
Known:   original_message, len(secret), MAC value
Compute: H(secret || original_message || padding || extension)
         WITHOUT knowing the secret!

How: The MAC value IS the internal hash state after processing
     (secret || original_message || padding).
     Initialize hash with this state, continue hashing extension.

1.3 Padding Calculation (MD5/SHA)

def md5_padding(message_len_bytes):
    """Calculate MD5/SHA padding for given message length."""
    bit_len = message_len_bytes * 8

    # Pad with 0x80 + zeros until length ≡ 56 (mod 64)
    padding = b'\x80'
    padding += b'\x00' * ((55 - message_len_bytes) % 64)

    # Append original length as 64-bit little-endian (MD5)
    # or big-endian (SHA)
    padding += bit_len.to_bytes(8, 'little')  # MD5
    # padding += bit_len.to_bytes(8, 'big')    # SHA

    return padding

1.4 Tool Usage

# HashPump
hashpump -s "known_mac_hex" \
         -d "original_data" \
         -k 16 \            # secret length
         -a "extension_data"

# Output: new_mac, new_data (original + padding + extension)

# hash_extender
hash_extender --data "original" \
              --secret 16 \
              --append "extension" \
              --signature "known_mac_hex" \
              --format md5

1.5 Python Implementation

import struct

def md5_extend(original_mac, original_data_len, secret_len, extension):
    """
    Perform MD5 length extension attack.
    original_mac: hex string of H(secret || original_data)
    """
    # Parse MAC into MD5 internal state (4 × 32-bit words, little-endian)
    h = struct.unpack('<4I', bytes.fromhex(original_mac))

    # Calculate total length after padding
    total_original = secret_len + original_data_len
    padding = md5_padding(total_original)
    forged_len = total_original + len(padding) + len(extension)

    # Continue MD5 from saved state with extension
    # (requires MD5 implementation that accepts initial state)
    from hashlib import md5
    # Most stdlib md5 doesn't expose state setting
    # Use: hlextend library or custom MD5

    import hlextend
    sha = hlextend.new('md5')
    new_hash = sha.extend(extension, original_data, secret_len,
                          original_mac)
    new_data = sha.payload  # includes original + padding + extension

    return new_hash, new_data

2. MD5 COLLISION ATTACKS

2.1 Identical-Prefix Collision (fastcoll)

Two messages with same prefix but different content, producing identical MD5.

# Generate collision pair
fastcoll -p prefix_file -o collision1.bin collision2.bin

# Result: MD5(collision1.bin) == MD5(collision2.bin)
# Files differ in exactly 128 bytes (two MD5 blocks)

2.2 Chosen-Prefix Collision (hashclash)

Two messages with different chosen prefixes, appended with computed suffixes to collide.

# hashclash (Marc Stevens)
./hashclash prefix1.bin prefix2.bin

# Result: MD5(prefix1 || suffix1) == MD5(prefix2 || suffix2)

2.3 UniColl (Single-Block Near-Collision)

Produces two messages differing in a single byte within one MD5 block, with same hash.

Application: forge two PDF/PE files with same MD5
  - File 1: benign content
  - File 2: malicious content
  - Same MD5 hash

2.4 Collision Applications

ApplicationTechniqueImpact
Certificate forgeryChosen-prefixRogue CA certificate (proven in 2008)
Binary substitutionIdentical-prefix + conditionalTwo executables, same MD5, different behavior
PDF collisionUniCollTwo PDFs showing different content
Git commit collisionChosen-prefix (SHAttered for SHA1)Two commits with same hash
CTF: bypass MD5 checkfastcollTwo different inputs accepted as same

2.5 CTF MD5 Collision Tricks

// PHP: md5($_GET['a']) == md5($_GET['b']) && $_GET['a'] != $_GET['b']

// Method 1: Array trick (not real collision)
?a[]=1&b[]=2  // md5(array) returns NULL, NULL == NULL

// Method 2: Real collision (fastcoll output, URL-encoded binary)
?a=<collision1_urlencoded>&b=<collision2_urlencoded>

// Method 3: 0e magic hashes (loose comparison ==)
// md5("240610708") = "0e462097431906509019562988736854"
// md5("QNKCDZO")   = "0e830400451993494058024219903391"
// PHP: "0e..." == "0e..." is TRUE (both evaluate to 0 as floats)

3. SHA-1 COLLISION

3.1 SHAttered Attack (2017)

First practical SHA-1 collision: two PDF files with same SHA-1.

  • Complexity: ~2^63 SHA-1 computations
  • Cost: ~$110K on GPU clusters (2017 prices)
  • Tool: shattered.io provides the collision PDFs

3.2 SHA-1 Chosen-Prefix Collision (2020)

  • Complexity: ~2^63.4 computations
  • Practical for attacking PGP/GnuPG key servers
  • Demonstrates SHA-1 is broken for collision resistance

3.3 Impact

SHA-1 should NOT be used for:
  ✗ Digital signatures
  ✗ Certificate fingerprints
  ✗ Git commit integrity (migration to SHA-256 in progress)
  ✗ Deduplication based on hash

SHA-1 is still OK for:
  ✓ HMAC-SHA1 (collision resistance not required)
  ✓ HKDF-SHA1 (PRF security suffices)
  ✓ Non-adversarial checksums

4. BIRTHDAY ATTACK

4.1 Generic Birthday Bound

For n-bit hash: expected collisions after ~2^(n/2) hashes

Hash     Bits    Birthday bound
MD5      128     2^64
SHA-1    160     2^80
SHA-256  256     2^128

CTF application: if hash is truncated to k bits,
collision in ~2^(k/2) attempts

4.2 Birthday Attack Implementation

import hashlib
import os

def birthday_attack(hash_func, output_bits, max_attempts=2**28):
    """Find collision for truncated hash."""
    mask = (1 << output_bits) - 1
    seen = {}

    for _ in range(max_attempts):
        msg = os.urandom(16)
        h = int(hash_func(msg).hexdigest(), 16) & mask

        if h in seen and seen[h] != msg:
            return seen[h], msg  # collision!
        seen[h] = msg

    return None

# Example: find collision for first 32 bits of SHA-256
result = birthday_attack(hashlib.sha256, 32)

5. HMAC TIMING ATTACK

Use this skill in a project

Open any RiverX project, search the Skills panel for yaklang/hack-skills/hash-attack-techniques, and install it in one click.

Use this skill