压缩文件 CRC32 碰撞原理解析以及制作解密脚本
字数 1473 2025-12-08 12:14:04

CRC32碰撞原理解析与解密脚本制作指南

一、CRC32基础概念

1.1 什么是CRC32校验

CRC32(Cyclic Redundancy Check 32)是一种32位循环冗余校验码,广泛应用于压缩文件格式(如ZIP、RAR)中,用于验证文件内容的完整性。它是一种线性校验和算法,能够检测数据传输或存储过程中出现的错误。

1.2 CRC32在压缩文件中的应用

在ZIP文件格式中,每个文件条目都包含一个CRC32校验值,该值基于未压缩的原始文件内容计算得出。即使文件内容被加密,CRC32值仍然以明文形式存储在文件头中,这为CRC32碰撞攻击提供了可能。

二、CRC32碰撞攻击原理

2.1 攻击的基本思路

CRC32碰撞攻击的核心原理是利用CRC32校验值空间有限(仅32位,即2^32≈42.9亿种可能)的特性,当压缩文件内文件内容很短时,可以通过暴力枚举的方式找到与目标CRC32值匹配的原始内容。

2.2 攻击的可行性条件

攻击成功的三个关键前提条件:

  1. 已知CRC32值:从压缩包文件头中获取
  2. 已知明文长度:通过文件头中的解压后大小字段获得
  3. 有限的字符集:明文字符集可预测或有限

2.3 数学原理分析

CRC32碰撞属于原像攻击(Pre-image Attack)的一种。给定哈希值H,寻找输入M使得CRC32(M)=H。当明文空间小于或接近2^32时,暴力枚举变得可行。

计算示例

  • 1字节明文:256种可能(瞬间完成)
  • 4字节明文:95^4≈8145万种可能(可接受时间)
  • 6字节明文:95^6≈7.35×10^11种可能(不可行)

三、实战案例解析

3.1 典型攻击场景

假设ZIP文件中包含一个2字节的文本文件,已知信息:

  • CRC32值:0x12345678
  • 明文长度:2字节
  • 字符集:ASCII可打印字符(95个)

3.2 攻击步骤

  1. 提取CRC32值:从ZIP文件头读取目标CRC32
  2. 确定搜索空间:95^2=9025种可能组合
  3. 暴力枚举:对每个候选明文计算CRC32并比较
  4. 结果验证:找到CRC32(AB)=0x12345678时,明文即为"AB"

四、解密脚本制作详解

4.1 脚本整体架构

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
CRC32碰撞解密脚本
功能:通过CRC32碰撞恢复ZIP文件中短文件的原始内容
"""

4.2 核心模块实现

4.2.1 CRC32计算函数

import binascii

def calculate_crc32(data):
    """计算数据的CRC32值(无符号32位)"""
    return binascii.crc32(data.encode()) & 0xffffffff

4.2.2 暴力枚举函数

import itertools

def brute_crc32(target_crc, length, charset):
    """
    暴力枚举CRC32原像
    :param target_crc: 目标CRC32值
    :param length: 明文长度
    :param charset: 字符集
    :return: 命中的明文字符串或None
    """
    target_crc &= 0xffffffff  # 确保无符号
    total = len(charset) ** length
    
    for combination in itertools.product(charset, repeat=length):
        candidate = ''.join(combination)
        crc_val = binascii.crc32(candidate.encode()) & 0xffffffff
        
        if crc_val == target_crc:
            return candidate
    
    return None

4.2.3 ZIP文件处理模块

import zipfile

def extract_zip_info(zip_path):
    """提取ZIP文件中各条目的CRC32和文件大小"""
    try:
        with zipfile.ZipFile(zip_path, 'r') as zf:
            file_info = {}
            for name in zf.namelist():
                info = zf.getinfo(name)
                file_info[name] = {
                    'crc': info.CRC & 0xffffffff,
                    'size': info.file_size
                }
            return file_info
    except Exception as e:
        print(f"错误: {e}")
        return None

4.3 字符集选择策略

提供多种字符集选项以适应不同场景:

import string

def select_charset(choice):
    """根据用户选择返回对应字符集"""
    charset_map = {
        '1': string.digits,                    # 数字 0-9
        '2': string.ascii_lowercase,           # 小写字母 a-z
        '3': string.ascii_uppercase,           # 大写字母 A-Z
        '4': string.ascii_letters,             # 所有字母
        '5': string.printable,                 # 可打印字符
        '6': custom_charset                    # 自定义字符集
    }
    return charset_map.get(choice, string.digits)

4.4 主控流程实现

def main_attack(zip_path, max_length=6):
    """主攻击函数"""
    # 1. 提取ZIP文件信息
    file_info = extract_zip_info(zip_path)
    if not file_info:
        return
    
    # 2. 用户交互配置
    charset = get_user_charset()
    
    # 3. 对每个文件进行攻击
    results = {}
    for filename, info in file_info.items():
        if info['size'] <= max_length:
            print(f"攻击文件: {filename} (大小: {info['size']}字节)")
            plaintext = brute_crc32(info['crc'], info['size'], charset)
            results[filename] = plaintext
    
    # 4. 输出结果
    print_results(results)

五、完整脚本代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import zipfile
import binascii
import itertools
import os
import string

def banner():
    print('+-----------------------------------------------------+')
    print('+               CRC32碰撞攻击工具                     +')
    print('+          小文件CRC32碰撞明文恢复脚本               +')
    print('+            仅限教学/CTF/合法授权使用               +')
    print('+-----------------------------------------------------+')

def choose_charset():
    """字符集选择函数"""
    print('请选择枚举字符集:')
    print(' [1] 数字 (0-9)')
    print(' [2] 小写字母 (a-z)')
    print(' [3] 大写字母 (A-Z)')
    print(' [4] 所有字母 (a-zA-Z)')
    print(' [5] 可打印字符 (string.printable)')
    print(' [6] 自定义字符集')
    
    choice = input('输入选项编号 [默认1]: ').strip()
    
    if choice == '2':
        return string.ascii_lowercase
    elif choice == '3':
        return string.ascii_uppercase
    elif choice == '4':
        return string.ascii_letters
    elif choice == '5':
        return string.printable
    elif choice == '6':
        raw = input('请输入自定义字符集: ')
        return ''.join(sorted(set(raw)))
    else:
        return string.digits

def brute_crc32(target_crc, length, charset):
    """CRC32暴力枚举函数"""
    target_crc &= 0xffffffff
    total = len(charset) ** length
    
    print(f'目标CRC32: 0x{target_crc:08x}')
    print(f'明文长度: {length}字节,字符集大小: {len(charset)}')
    print(f'搜索空间: {total}种可能')
    
    if total > 1e8:
        print('警告: 搜索空间过大,可能需要较长时间')
    
    count = 0
    for combination in itertools.product(charset, repeat=length):
        candidate = ''.join(combination)
        crc_val = binascii.crc32(candidate.encode()) & 0xffffffff
        count += 1
        
        if crc_val == target_crc:
            print(f'命中! 尝试次数: {count}, 明文: {repr(candidate)}')
            return candidate
        
        if count % 1000000 == 0:
            print(f'已尝试: {count}/{total}')
    
    print('未找到匹配明文')
    return None

def crack_zip_crc(zip_path, max_length=4):
    """主攻击函数"""
    if not os.path.exists(zip_path):
        print(f'文件不存在: {zip_path}')
        return
    
    try:
        zf = zipfile.ZipFile(zip_path, 'r')
    except Exception as e:
        print(f'打开ZIP文件失败: {e}')
        return
    
    charset = choose_charset()
    results = {}
    
    for name in zf.namelist():
        info = zf.getinfo(name)
        crc = info.CRC & 0xffffffff
        size = info.file_size
        
        print(f'\n文件: {name}')
        print(f'大小: {size}字节, CRC32: 0x{crc:08x}')
        
        if size > max_length:
            print('文件过大,跳过')
            continue
        
        plaintext = brute_crc32(crc, size, charset)
        results[name] = plaintext
    
    zf.close()
    
    # 输出最终结果
    print('\n' + '='*50)
    print('攻击结果汇总:')
    for name, pt in results.items():
        status = repr(pt) if pt else '未找到'
        print(f'{name}: {status}')

def main():
    banner()
    zip_path = input('请输入ZIP文件路径: ').strip()
    if zip_path:
        crack_zip_crc(zip_path)

if __name__ == '__main__':
    main()

六、攻击优化与注意事项

6.1 性能优化策略

  1. 并行计算:使用多进程并行处理不同字符块
  2. 早期终止:对部分字符集实现智能剪枝
  3. 彩虹表:对常用字符集预计算CRC32映射

6.2 使用限制与注意事项

  1. 文件长度限制:通常只适用于1-6字节的短文件
  2. 字符集选择:字符集越大,攻击时间呈指数增长
  3. 误报可能:存在不同明文产生相同CRC32的可能性
  4. 法律合规:仅限授权测试和教育用途

6.3 实际应用场景

  1. CTF竞赛:解决包含短文本的加密ZIP挑战
  2. 数字取证:恢复损坏压缩包中的关键短文件
  3. 密码学教学:理解哈希函数碰撞原理

七、总结

CRC32碰撞攻击是利用CRC32校验值空间有限的特性,通过暴力枚举恢复短文件内容的有效方法。虽然适用场景有限,但在特定条件下(文件长度短、字符集可控)具有很高的实用价值。本教学文档详细介绍了攻击原理、实现方法和注意事项,为相关领域的技术人员提供了完整的技术参考。

重要提醒:本技术应仅用于合法授权的安全测试、CTF竞赛和教育研究目的,严禁用于任何非法活动。

CRC32碰撞原理解析与解密脚本制作指南 一、CRC32基础概念 1.1 什么是CRC32校验 CRC32(Cyclic Redundancy Check 32)是一种32位循环冗余校验码,广泛应用于压缩文件格式(如ZIP、RAR)中,用于验证文件内容的完整性。它是一种线性校验和算法,能够检测数据传输或存储过程中出现的错误。 1.2 CRC32在压缩文件中的应用 在ZIP文件格式中,每个文件条目都包含一个CRC32校验值,该值基于未压缩的原始文件内容计算得出。即使文件内容被加密,CRC32值仍然以明文形式存储在文件头中,这为CRC32碰撞攻击提供了可能。 二、CRC32碰撞攻击原理 2.1 攻击的基本思路 CRC32碰撞攻击的核心原理是利用CRC32校验值空间有限(仅32位,即2^32≈42.9亿种可能)的特性,当压缩文件内文件内容很短时,可以通过暴力枚举的方式找到与目标CRC32值匹配的原始内容。 2.2 攻击的可行性条件 攻击成功的三个关键前提条件: 已知CRC32值 :从压缩包文件头中获取 已知明文长度 :通过文件头中的解压后大小字段获得 有限的字符集 :明文字符集可预测或有限 2.3 数学原理分析 CRC32碰撞属于原像攻击(Pre-image Attack)的一种。给定哈希值H,寻找输入M使得CRC32(M)=H。当明文空间小于或接近2^32时,暴力枚举变得可行。 计算示例 : 1字节明文:256种可能(瞬间完成) 4字节明文:95^4≈8145万种可能(可接受时间) 6字节明文:95^6≈7.35×10^11种可能(不可行) 三、实战案例解析 3.1 典型攻击场景 假设ZIP文件中包含一个2字节的文本文件,已知信息: CRC32值:0x12345678 明文长度:2字节 字符集:ASCII可打印字符(95个) 3.2 攻击步骤 提取CRC32值 :从ZIP文件头读取目标CRC32 确定搜索空间 :95^2=9025种可能组合 暴力枚举 :对每个候选明文计算CRC32并比较 结果验证 :找到CRC32(AB)=0x12345678时,明文即为"AB" 四、解密脚本制作详解 4.1 脚本整体架构 4.2 核心模块实现 4.2.1 CRC32计算函数 4.2.2 暴力枚举函数 4.2.3 ZIP文件处理模块 4.3 字符集选择策略 提供多种字符集选项以适应不同场景: 4.4 主控流程实现 五、完整脚本代码 六、攻击优化与注意事项 6.1 性能优化策略 并行计算 :使用多进程并行处理不同字符块 早期终止 :对部分字符集实现智能剪枝 彩虹表 :对常用字符集预计算CRC32映射 6.2 使用限制与注意事项 文件长度限制 :通常只适用于1-6字节的短文件 字符集选择 :字符集越大,攻击时间呈指数增长 误报可能 :存在不同明文产生相同CRC32的可能性 法律合规 :仅限授权测试和教育用途 6.3 实际应用场景 CTF竞赛 :解决包含短文本的加密ZIP挑战 数字取证 :恢复损坏压缩包中的关键短文件 密码学教学 :理解哈希函数碰撞原理 七、总结 CRC32碰撞攻击是利用CRC32校验值空间有限的特性,通过暴力枚举恢复短文件内容的有效方法。虽然适用场景有限,但在特定条件下(文件长度短、字符集可控)具有很高的实用价值。本教学文档详细介绍了攻击原理、实现方法和注意事项,为相关领域的技术人员提供了完整的技术参考。 重要提醒 :本技术应仅用于合法授权的安全测试、CTF竞赛和教育研究目的,严禁用于任何非法活动。