hash-attack-techniques

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: Hash Attack Techniques — Expert Cryptanalysis Playbook

SKILL:哈希攻击技术——专家级密码分析手册

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.
AI加载说明:适用于CTF和安全评估的专家级哈希攻击技术,涵盖长度扩展攻击、MD5/SHA1碰撞生成、中间相遇哈希攻击、HMAC时序侧信道、生日攻击以及工作量证明求解。基础模型通常会错误地将长度扩展攻击应用于HMAC或SHA-3,或者无法区分相同前缀碰撞和选择前缀碰撞。

0. RELATED ROUTING

0. 相关路由

  • 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
  • 当哈希漏洞影响RSA签名方案时,参考rsa-attack-techniques
  • 当哈希用于密钥派生时,参考symmetric-cipher-attacks
  • 当分析古典密码中的类哈希构造时,参考classical-cipher-analysis

Quick attack selection

快速攻击选择

ScenarioAttackTool
H(secret || msg)
known, extend message
Length 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

场景攻击方式工具
已知`H(secretmsg)`,需要扩展消息
需要两个MD5相同的文件相同前缀碰撞fastcoll
需要匹配特定MD5前缀选择前缀碰撞hashclash
逐字节HMAC比较时序攻击自定义脚本
查找任意碰撞生日攻击O(2^(n/2))
工作量证明:查找带前导零的哈希暴力破解hashcat, Python

1. LENGTH EXTENSION ATTACK

1. 长度扩展攻击

1.1 Vulnerable vs Non-Vulnerable

1.1 易受攻击 vs 不受影响的哈希算法

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
哈希算法是否易受攻击原因
MD5Merkle-Damgard 构造
SHA-1Merkle-Damgard 构造
SHA-256Merkle-Damgard 构造
SHA-512Merkle-Damgard 构造
SHA-3 / KeccakSponge 构造
HMAC-*双重哈希防止扩展
截断版SHA-256否(如果截断)缺失内部状态位
BLAKE2不同的构造逻辑

1.2 Attack Mechanism

1.2 攻击原理

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.
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)

1.3 填充计算(MD5/SHA)

python
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
python
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

1.4 工具使用

bash
undefined
bash
undefined

HashPump

HashPump

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

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

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

hash_extender

hash_extender

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

1.5 Python Implementation

1.5 Python实现

python
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

python
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. MD5碰撞攻击

2.1 Identical-Prefix Collision (fastcoll)

2.1 相同前缀碰撞(fastcoll)

Two messages with same prefix but different content, producing identical MD5.
bash
undefined
两个前缀相同但内容不同的消息,生成相同的MD5值。
bash
undefined

Generate collision pair

Generate collision pair

fastcoll -p prefix_file -o collision1.bin collision2.bin
fastcoll -p prefix_file -o collision1.bin collision2.bin

Result: MD5(collision1.bin) == MD5(collision2.bin)

Result: MD5(collision1.bin) == MD5(collision2.bin)

Files differ in exactly 128 bytes (two MD5 blocks)

Files differ in exactly 128 bytes (two MD5 blocks)

undefined
undefined

2.2 Chosen-Prefix Collision (hashclash)

2.2 选择前缀碰撞(hashclash)

Two messages with different chosen prefixes, appended with computed suffixes to collide.
bash
undefined
两个带有不同选择前缀的消息,附加计算出的后缀后产生碰撞。
bash
undefined

hashclash (Marc Stevens)

hashclash (Marc Stevens)

./hashclash prefix1.bin prefix2.bin
./hashclash prefix1.bin prefix2.bin

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

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

undefined
undefined

2.3 UniColl (Single-Block Near-Collision)

2.3 UniColl(单块近碰撞)

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
生成两个在单个MD5块内仅相差一个字节的消息,拥有相同的哈希值。
应用场景:伪造两个MD5相同的PDF/PE文件
  - 文件1:良性内容
  - 文件2:恶意内容
  - 相同MD5哈希

2.4 Collision Applications

2.4 碰撞应用场景

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
应用技术影响
证书伪造选择前缀伪造CA证书(2008年已被证实)
二进制文件替换相同前缀+条件判断两个MD5相同、行为不同的可执行文件
PDF碰撞UniColl两个显示不同内容的PDF
Git提交碰撞选择前缀(针对SHA1的SHAttered攻击)两个哈希相同的提交
CTF:绕过MD5校验fastcoll两个不同输入被判定为相同

2.5 CTF MD5 Collision Tricks

2.5 CTF MD5碰撞技巧

php
// 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)

php
// 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. SHA-1碰撞

3.1 SHAttered Attack (2017)

3.1 SHAttered攻击(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
首个实用的SHA-1碰撞:两个SHA-1相同的PDF文件。
  • 复杂度:约2^63次SHA-1计算
  • 成本:在GPU集群上约11万美元(2017年价格)
  • 工具:shattered.io提供碰撞PDF

3.2 SHA-1 Chosen-Prefix Collision (2020)

3.2 SHA-1选择前缀碰撞(2020)

  • Complexity: ~2^63.4 computations
  • Practical for attacking PGP/GnuPG key servers
  • Demonstrates SHA-1 is broken for collision resistance
  • 复杂度:约2^63.4次计算
  • 可用于攻击PGP/GnuPG密钥服务器
  • 证明SHA-1的碰撞抵抗性已被攻破

3.3 Impact

3.3 影响

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

SHA-1 不应用于以下场景:
  ✗ 数字签名
  ✗ 证书指纹
  ✗ Git提交完整性校验(正在迁移到SHA-256)
  ✗ 基于哈希的去重

SHA-1 仍可安全用于以下场景:
  ✓ HMAC-SHA1(不需要碰撞抵抗性)
  ✓ HKDF-SHA1(PRF安全性足够)
  ✓ 非对抗性场景的校验和

4. BIRTHDAY ATTACK

4. 生日攻击

4.1 Generic Birthday Bound

4.1 通用生日边界

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
对于n位哈希:约2^(n/2)次哈希计算后大概率出现碰撞

哈希算法     位数    生日边界
MD5      128     2^64
SHA-1    160     2^80
SHA-256  256     2^128

CTF应用场景:如果哈希被截断为k位,约2^(k/2)次尝试即可找到碰撞

4.2 Birthday Attack Implementation

4.2 生日攻击实现

python
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
python
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

Example: find collision for first 32 bits of SHA-256

result = birthday_attack(hashlib.sha256, 32)

---
result = birthday_attack(hashlib.sha256, 32)

---

5. HMAC TIMING ATTACK

5. HMAC时序攻击

5.1 Vulnerable Comparison

5.1 易受攻击的比较逻辑

python
undefined
python
undefined

VULNERABLE: early-exit string comparison

存在漏洞:提前退出的字符串比较

def verify_hmac(received, expected): return received == expected # Python == compares left to right
def verify_hmac(received, expected): return received == expected # Python == 从左到右比较

The comparison may short-circuit on first differing byte,

比较会在第一个不同字节处短路,泄露时序信息

leaking timing information

undefined
undefined

5.2 Attack Strategy

5.2 攻击策略

python
import requests
import time

def hmac_timing_attack(url, data, hmac_len=32):
    """Byte-by-byte HMAC recovery via timing."""
    known = ""

    for pos in range(hmac_len * 2):  # hex chars
        best_char = ""
        best_time = 0

        for c in "0123456789abcdef":
            candidate = known + c + "0" * (hmac_len * 2 - len(known) - 1)
            times = []

            for _ in range(50):  # multiple samples for accuracy
                start = time.perf_counter_ns()
                requests.get(url, params={**data, "mac": candidate})
                elapsed = time.perf_counter_ns() - start
                times.append(elapsed)

            avg_time = sorted(times)[len(times)//2]  # median
            if avg_time > best_time:
                best_time = avg_time
                best_char = c

        known += best_char
        print(f"Position {pos}: {known}")

    return known
python
import requests
import time

def hmac_timing_attack(url, data, hmac_len=32):
    """Byte-by-byte HMAC recovery via timing."""
    known = ""

    for pos in range(hmac_len * 2):  # hex chars
        best_char = ""
        best_time = 0

        for c in "0123456789abcdef":
            candidate = known + c + "0" * (hmac_len * 2 - len(known) - 1)
            times = []

            for _ in range(50):  # multiple samples for accuracy
                start = time.perf_counter_ns()
                requests.get(url, params={**data, "mac": candidate})
                elapsed = time.perf_counter_ns() - start
                times.append(elapsed)

            avg_time = sorted(times)[len(times)//2]  # median
            if avg_time > best_time:
                best_time = avg_time
                best_char = c

        known += best_char
        print(f"Position {pos}: {known}")

    return known

5.3 Constant-Time Comparison (Defense)

5.3 恒时比较(防御方案)

python
import hmac
python
import hmac

SECURE: constant-time comparison

安全:恒时比较

def verify_hmac_secure(received, expected): return hmac.compare_digest(received, expected)

---
def verify_hmac_secure(received, expected): return hmac.compare_digest(received, expected)

---

6. MEET-IN-THE-MIDDLE (HASH)

6. 中间相遇攻击(哈希)

6.1 Concept

6.1 概念

Split hash computation into two halves, precompute one, match against the other.
Hash computation: H = f(g(x₁), h(x₂))

Precompute: table[g(x₁)] = x₁  for all x₁ in space₁
Search:     for each x₂ in space₂:
              if h(x₂) in table:
                found! (x₁, x₂)

Time:  O(2^(n/2)) instead of O(2^n)
Space: O(2^(n/2))

将哈希计算拆分为两部分,预计算其中一部分,与另一部分匹配。
Hash computation: H = f(g(x₁), h(x₂))

Precompute: table[g(x₁)] = x₁  for all x₁ in space₁
Search:     for each x₂ in space₂:
              if h(x₂) in table:
                found! (x₁, x₂)

Time:  O(2^(n/2)) instead of O(2^n)
Space: O(2^(n/2))

7. HASH PROOF-OF-WORK

7. 哈希工作量证明

7.1 Common CTF PoW Formats

7.1 常见CTF工作量证明格式

python
undefined
python
undefined

Format 1: Find x such that SHA256(prefix + x) starts with N zero bits

格式1:查找x使得SHA256(prefix + x)以N个零比特开头

import hashlib
def solve_pow_prefix(prefix, zero_bits): target = '0' * (zero_bits // 4) i = 0 while True: candidate = prefix + str(i) h = hashlib.sha256(candidate.encode()).hexdigest() if h.startswith(target): return str(i) i += 1
import hashlib
def solve_pow_prefix(prefix, zero_bits): target = '0' * (zero_bits // 4) i = 0 while True: candidate = prefix + str(i) h = hashlib.sha256(candidate.encode()).hexdigest() if h.startswith(target): return str(i) i += 1

Format 2: Find x such that SHA256(x) ends with specific suffix

格式2:查找x使得SHA256(x)以特定后缀结尾

def solve_pow_suffix(suffix_hex, hash_func=hashlib.sha256): i = 0 while True: h = hash_func(str(i).encode()).hexdigest() if h.endswith(suffix_hex): return str(i) i += 1
undefined
def solve_pow_suffix(suffix_hex, hash_func=hashlib.sha256): i = 0 while True: h = hash_func(str(i).encode()).hexdigest() if h.endswith(suffix_hex): return str(i) i += 1
undefined

7.2 GPU-Accelerated PoW

7.2 GPU加速的工作量证明求解

bash
undefined
bash
undefined

hashcat for SHA256 PoW

hashcat for SHA256 PoW

hashcat -a 3 -m 1400 --hex-charset
"0000000000000000000000000000000000000000000000000000000000000000:prefix"
"?a?a?a?a?a?a?a?a"

---
hashcat -a 3 -m 1400 --hex-charset
"0000000000000000000000000000000000000000000000000000000000000000:prefix"
"?a?a?a?a?a?a?a?a"

---

8. RAINBOW TABLES & SALTING

8. 彩虹表与加盐

8.1 Rainbow Table Attack

8.1 彩虹表攻击

Precomputed chain: password → hash → reduce → password₂ → hash₂ → ...
Lookup: given hash h, check if h appears in any chain
Time-memory tradeoff: less space than full table, more time than direct lookup
预计算链:密码 → 哈希 → 归约 → 密码2 → 哈希2 → ...
查找:给定哈希h,检查h是否出现在任意链中
时间内存权衡:比全量表占用空间少,比直接查找耗时多

8.2 Salt Defeats Rainbow Tables

8.2 加盐可抵御彩虹表

Without salt: H(password) — same password always produces same hash
With salt:    H(salt || password) — different salt per user

Rainbow tables are password-specific, not (salt+password)-specific
Each unique salt requires a separate table → infeasible
不加盐:H(密码) — 相同密码始终生成相同哈希
加盐:H(盐 || 密码) — 每个用户使用不同的盐

彩虹表是针对密码的,不是针对(盐+密码)的
每个唯一盐都需要单独的彩虹表 → 实际不可行

8.3 Modern Password Hashing

8.3 现代密码哈希算法

AlgorithmSaltIterationsMemory-HardRecommended
MD5No1NoNever
SHA-256No1NoNever for passwords
bcryptYesConfigurableNoYes
scryptYesConfigurableYesYes
Argon2YesConfigurableYesBest choice
PBKDF2YesConfigurableNoAcceptable

算法加盐迭代次数内存硬加密推荐程度
MD51绝不使用
SHA-2561绝不用作密码哈希
bcrypt可配置推荐
scrypt可配置推荐
Argon2可配置最佳选择
PBKDF2可配置可接受

9. DECISION TREE

9. 决策树

Hash-related challenge — what's the scenario?
├─ Have H(secret || message), need to extend?
│  ├─ Hash is MD5/SHA1/SHA256/SHA512?
│  │  └─ Yes → Length extension attack
│  │     └─ Need: MAC value, original message, secret length
│  │        └─ Tool: HashPump or hash_extender
│  │
│  └─ Hash is SHA3/HMAC/BLAKE2?
│     └─ Length extension doesn't work
│        └─ Look for other vulnerabilities
├─ Need two inputs with same hash?
│  ├─ MD5?
│  │  ├─ Same prefix → fastcoll (seconds)
│  │  ├─ Different prefixes → hashclash (hours)
│  │  └─ CTF PHP loose comparison → 0e magic hashes
│  │
│  ├─ SHA-1?
│  │  └─ SHAttered (expensive, use precomputed if possible)
│  │
│  └─ SHA-256+?
│     └─ No practical collision attack
│        └─ Look for logic flaws instead
├─ Need to forge HMAC?
│  ├─ Timing side channel available?
│  │  └─ Byte-by-byte timing attack
│  │
│  ├─ Key is short/weak?
│  │  └─ Brute force key with hashcat
│  │
│  └─ No weakness?
│     └─ HMAC is secure — look elsewhere
├─ Hash is truncated (short output)?
│  └─ Birthday attack — collision in 2^(bits/2)
├─ Proof of work?
│  └─ Brute force with parallel computation
│     ├─ Python multiprocessing for < 28 bits
│     ├─ hashcat/GPU for > 28 bits
│     └─ Optimize: pre-increment string, avoid re-encoding
└─ Password hash cracking?
   ├─ No salt → rainbow tables (pre-computed)
   ├─ Known salt → hashcat / John the Ripper
   └─ Memory-hard (Argon2/scrypt) → limited by memory, slow brute force

哈希相关挑战 — 当前场景是什么?
├─ 持有H(secret || message),需要扩展消息?
│  ├─ 哈希算法是MD5/SHA1/SHA256/SHA512?
│  │  └─ 是 → 长度扩展攻击
│  │     └─ 需要:MAC值、原始消息、密钥长度
│  │        └─ 工具:HashPump 或 hash_extender
│  │
│  └─ 哈希算法是SHA3/HMAC/BLAKE2?
│     └─ 长度扩展攻击不生效
│        └─ 查找其他漏洞
├─ 需要两个哈希相同的输入?
│  ├─ 是MD5?
│  │  ├─ 相同前缀 → fastcoll(秒级)
│  │  ├─ 不同前缀 → hashclash(小时级)
│  │  └─ CTF PHP弱类型比较 → 0e魔法哈希
│  │
│  ├─ 是SHA-1?
│  │  └─ SHAttered(成本高,优先使用预计算结果)
│  │
│  └─ 是SHA-256及以上?
│     └─ 无实用碰撞攻击
│        └─ 转而查找逻辑漏洞
├─ 需要伪造HMAC?
│  ├─ 存在时序侧信道?
│  │  └─ 逐字节时序攻击
│  │
│  ├─ 密钥短/弱?
│  │  └─ 用hashcat暴力破解密钥
│  │
│  └─ 无漏洞?
│     └─ HMAC是安全的 — 查找其他方向
├─ 哈希被截断(输出较短)?
│  └─ 生日攻击 — 2^(位数/2)次尝试即可碰撞
├─ 工作量证明?
│  └─ 并行计算暴力破解
│     ├─ <28位用Python多进程
│     ├─ >28位用hashcat/GPU
│     └─ 优化:预增量字符串,避免重复编码
└─ 密码哈希破解?
   ├─ 无盐 → 彩虹表(预计算)
   ├─ 已知盐 → hashcat / John the Ripper
   └─ 内存硬加密(Argon2/scrypt) → 受内存限制,暴力破解速度慢

10. TOOLS

10. 工具

ToolPurposeUsage
HashPumpLength extension attack
hashpump -s MAC -d data -k secret_len -a extension
hash_extenderLength extension (multiple algorithms)
hash_extender --data D --secret L --append E --sig MAC
fastcollMD5 identical-prefix collision
fastcoll -p prefix -o out1 out2
hashclashMD5 chosen-prefix collision
hashclash prefix1 prefix2
hashcatPassword/hash cracking (GPU)
hashcat -m MODE -a ATTACK hash wordlist
John the RipperPassword cracking (CPU/GPU)
john --wordlist=rockyou.txt hashes.txt
CyberChefQuick hash computation and encodingWeb-based
工具用途用法
HashPump长度扩展攻击
hashpump -s MAC -d data -k secret_len -a extension
hash_extender长度扩展攻击(支持多种算法)
hash_extender --data D --secret L --append E --sig MAC
fastcollMD5相同前缀碰撞
fastcoll -p prefix -o out1 out2
hashclashMD5选择前缀碰撞
hashclash prefix1 prefix2
hashcat密码/哈希破解(GPU加速)
hashcat -m MODE -a ATTACK hash wordlist
John the Ripper密码破解(CPU/GPU)
john --wordlist=rockyou.txt hashes.txt
CyberChef快速哈希计算与编码网页版工具