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}")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}")完整脚本
将以上步骤整合为一个完整的 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 时会忽略多余数据,但部分在线服务可能拒绝)
- 对于更严格的场景(如法庭证据哈希校验),此方法不可靠,应使用更隐蔽的隐写方式
- 此方法同样适用于其他文件类型(视频、压缩包等),但需验证目标应用是否能正常处理尾部冗余数据




