AI摘要

文章介绍利用Python在图片末尾追加冗余数据改变MD5的方法。此法不影响图片显示,可用于绕过哈希去重,但会导致文件体积增大。

利用 Python 在图片末尾追加冗余数据,从而改变其 MD5 散列值,适用于绕过基于哈希的图片去重或简单校验场景。


MD5 简介

MD5(Message-Digest Algorithm) 是一种广泛使用的密码散列函数,由 Ronald Rivest 于 1991 年设计。它接受任意长度的输入,产生一个 128 位(16 字节) 的散列值,通常表示为 32 位的十六进制字符串。

MD5 的核心特性:

  • 确定性 — 同一文件始终产生相同散列值
  • 雪崩效应 — 输入微小变化即导致输出完全改变
  • 不可逆性 — 无法从散列值还原原始内容
MD5 在抗碰撞性上已被证明存在弱点(2004 年王小云团队提出碰撞攻击),但在文件完整性校验等非安全场景中仍被广泛使用。

修改原理

文件哈希计算方式

文件的 MD5 是对文件的全部二进制内容逐字节计算得出的。因此,如果文件内容发生任何变化,MD5 值就会完全不同。

策略:追加不影响正常使用的冗余数据

对于图片文件(如 JPEG、PNG),在文件末尾追加数据不会影响图片的正常显示。图片解码器在读取到文件结束标记(如 JPEG 的 FFD9)后会停止解析,忽略尾部多余内容。

因此,只需要在图片末尾写入一段额外字符串,就能在不破坏图片可视内容的前提下,彻底改变其 MD5。


实现代码

1. 计算图片原始 MD5

import hashlib

path = "a.jpg"

with open(path, "rb") as f:
    data = f.read()
    md5 = hashlib.md5(data).hexdigest()

print(f"原始 MD5: {md5}")

计算原始 MD5

2. 修改 MD5

将当前时间戳(毫秒级)以字符串形式追加到图片末尾。时间戳每次执行都不同,从而实现每次修改产生不同的 MD5。

import time

path = "a.jpg"
suffix = str(int(time.time() * 1000))

with open(path, "a") as f:
    f.write(suffix)

代码说明:

语句作用
int(time.time() * 1000)获取当前 Unix 时间戳(毫秒级)
open(path, "a")追加模式打开文件,指针在末尾
f.write(str(writefile))将时间戳字符串写入文件末尾
为什么不直接随机写一段固定字符串?
使用毫秒时间戳作为后缀可以保证每次执行的写入内容都不相同,避免第二次执行时因写入相同内容导致 MD5 不变。

3. 验证 MD5 已变更

再次计算文件 MD5,对比之前的值确认已改变:

import hashlib

with open(path, "rb") as f:
    data = f.read()
    new_md5 = hashlib.md5(data).hexdigest()

print(f"修改后 MD5: {new_md5}")

验证 MD5 已变更


完整脚本

将以上步骤整合为一个完整的 Python 脚本:

import time
import hashlib

path = "a.jpg"

def calc_md5(filepath):
    with open(filepath, "rb") as f:
        return hashlib.md5(f.read()).hexdigest()

# 原始 MD5
original = calc_md5(path)
print(f"[*] 原始 MD5: {original}")

# 追加时间戳
suffix = str(int(time.time() * 1000))
with open(path, "a") as f:
    f.write(suffix)

# 新的 MD5
new_md5 = calc_md5(path)
print(f"[*] 修改后 MD5: {new_md5}")
print(f"[*] 是否变化: {original != new_md5}")

应用场景

场景说明
图床去重绕过部分图床基于 MD5 检测重复图片,追加尾部数据可绕过
文件完整性校验绕过绕过简单的哈希校验检查
社交平台重复图片检测部分平台使用图片 MD5 判断是否为重复上传
本地文件去重使相同内容的不同版本具有不同哈希值

注意事项

  • 每次执行追加都会使文件体积增大,反复执行会导致图片体积膨胀
  • 某些图片查看器或服务可能对文件末尾的额外数据做严格校验(如部分浏览器在显示 JPEG 时会忽略多余数据,但部分在线服务可能拒绝)
  • 对于更严格的场景(如法庭证据哈希校验),此方法不可靠,应使用更隐蔽的隐写方式
  • 此方法同样适用于其他文件类型(视频、压缩包等),但需验证目标应用是否能正常处理尾部冗余数据
投币支持一下吧
END