文章总结: 本文介绍了一种无需训练和数据集,直接修改PyTorch模型权重文件来植入后门的方法。它利用PyTorch权重文件本质为ZIP包的特性,通过解压、修改全连接层偏置(bias)的二进制数值、再重新打包,即可精准操控模型预测结果,使其更倾向于特定类别(如将图片误判为狗)。文章还提供了不同增量对攻击效果的测试数据与自动化脚本。
综合评分: 85
文章分类: AI安全,恶意软件,供应链安全,漏洞分析,技术标准
【AI安全】零训练成本到模型后门植入
原创
十月的进阶之路 十月的进阶之路
十月的进阶之路
2026年3月29日 22:18 甘肃
供应链攻击的隐蔽新玩法,全程无需数据集、无需重新训练
0x01 背景
在上一篇《模型后门之木马攻击》中,我们通过给ResNet50外挂神经网络、构造带触发器的数据集完成训练,实现了特定触发模式的后门攻击。但这套方案流程繁琐,既要定制化制作训练数据,还要让模型重新学习触发器的映射规律,如同老太太的裹脚布又臭又长。这一次我们玩个更有趣的:如果能拿到目标模型的权重文件,我们能不能直接修改权重数值,完成一次精准的供应链攻击?当然是可以的,而且全程零训练、零数据集依赖,只需要修改几个字节,就能操控模型的预测结果。
0x02 PyTorch权重文件结构
我们还是沿用之前用于CIFAR-10数据集分类的best_model_bak.pth权重文件,先大概了解它的内部结构,以便于精准修改。当然神经网络逆向工程也是个前沿的领域,如果您有兴趣的话我也乐于分享。
2.1 权重文件的本质:ZIP归档包
把权重文件拖入任意二进制编辑器,第一眼就能看到文件开头的504B0304魔数,对应的ASCII字符是PK——这是ZIP归档文件的标准标识。
权重文件结构
这说明,这是PyTorch 1.6+版本默认的ZIP格式权重文件,而非旧版的纯pickle单文件。从PyTorch 1.6开始,torch.save默认用ZIP格式打包权重,把「模型元数据」和「张量纯数值数据」分离存储,既提升了加载效率,也增强了稳定性。继续往下看,我们能从二进制内容里提取到更多关键信息:
权重文件结构
从层名的命名规律(conv1→bn1→layer1/layer2/layer3/layer4残差块),可以大概率确定这是一个ResNet系列的CNN卷积神经网络(大概率是ResNet18/34/50等经典分类网络),并且包含完整的BatchNorm层running统计量,是训练完成的可直接推理的权重。同时能看到.cuda:0标识,说明这个模型是在CUDA GPU上完成训练并保存的。
2.2 解压后:权重文件的完整目录结构
既然本质是ZIP包,我们直接解压,就能看到它的完整内部结构。
权重文件结构
下面我们逐个拆解每个文件/文件夹的核心作用,搞懂PyTorch加载权重的完整流程:
| 文件/文件夹 | 核心作用 |
| — | — |
| version | 序列化协议版本标识,PyTorch加载时会先校验版本兼容性,避免格式不匹配导致加载失败 |
| byteorder | 字节序标识,记录张量二进制数据的存储顺序(x86/ARM架构和NVIDIA GPU默认都是小端序little),PyTorch需要靠它正确解析二进制数值 |
| .data/serialization_id | 全局唯一序列化ID,torch.save执行时随机生成,用于校验元数据和张量数据的一致性,避免跨文件引用错乱 |
| data.pkl | 权重的「核心蓝图+索引目录」,Python Pickle序列化格式,存储了完整的模型层名、张量形状、数据类型,以及每个张量对应data/目录下的文件索引,是把二进制数据还原成可用张量的关键 |
| data/ | 权重的「纯数值仓库」,里面的每个数字命名文件,都对应一个张量的原始二进制数据,没有任何元数据,单独打开是无意义的乱码 |
各文件的具体结构如下图所示:
serialization_id文件
data.pkl文件
data目录文件
当你调用torch.load("best_model")时,PyTorch内部会按以下步骤完整重建模型权重:
- 读取
version和byteorder,确认格式兼容性和数据解析规则; - 反序列化
data.pkl,解析出所有层名、张量元数据,以及对应data/目录的文件索引; - 根据索引,逐个读取
data/目录下的二进制文件; - 结合张量形状、数据类型、字节序,把二进制数据还原成PyTorch张量;
- 把层名和张量组装成
collections.OrderedDict格式的state_dict,完成权重加载。
0x03 为什么改权重能操控模型预测?
我们的目标是让模型在CIFAR-10数据集上,更倾向于把图片判别为「狗」,先明确两个关键前提:
3.1 CIFAR-10的类别索引对应
CIFAR-10数据集是10分类任务,采用0-based索引,类别顺序固定如下:
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | | — | — | — | — | — | — | — | — | — | — | — | | 类别 | 飞机 | 汽车 | 鸟 | 猫 | 鹿 | 狗 | 青蛙 | 马 | 船 | 卡车 |
我们要操控的「狗」,对应索引5,也就是1-based计数的第6个数值。
3.2 为什么修改全连接层bias就能直接提升概率?
模型最后一层全连接层的输出公式为:
最终的类别概率,由softmax(logits)归一化计算得出。
- 全连接层的
bias_i,是对应类别i的固定偏置项,直接决定了该类别logit的基础值; - 我们手动增大
bias_5,就相当于给「狗」这个类别加了一个固定的“加分项”,logit值变大后,经过softmax归一化,该类别的输出概率会显著提升; - 哪怕图片本身和狗无关,模型在难以判别时,也会有更高概率把它判定为狗,实现我们想要的后门效果。
回到我们的权重文件,data/目录下有一个40字节的文件,对应全连接层的bias:PyTorch默认用float32单精度浮点数存储权重,每个数值占4字节,40字节刚好对应10个数值,完美匹配CIFAR-10的10个分类。
0x04 手动修改权重实现后门
4.1 手动修改的关键注意事项
- 数值格式:必须使用IEEE 754标准的float32单精度浮点数,不能直接写入十进制数;
- 字节序:必须遵循小端序规则,数值的十六进制需要倒序存储;
- 文件大小:修改时只能覆盖字节,不能插入/删除字节,否则会导致文件大小变化,元数据匹配失败,权重无法加载;
- 打包规则:重新打包ZIP时,必须使用「存储(无压缩)」模式,且目录结构必须符合PyTorch的要求,否则会加载报错。
4.2 完整修改步骤
找到目标文件:定位到全连接层bias对应的data/目录下的二进制文件,我们要修改索引5(第6个)的数值,对应文件内偏移0x14 ~ 0x17的4个字节。
权重文件修改
数值转换:通过IEEE 754浮点数转换工具,把你想要的目标数值,转换为float32格式的十六进制,再按小端序反转。
查看原始权重的十进制数值大小
选择合适的替换值
写入修改:用十六进制编辑器(如HxD)打开目标文件,覆盖对应偏移的4个字节,保存文件。
手动修改数值转换
重新打包:按PyTorch要求的格式,用「存储模式」重新打包为ZIP文件,修改后缀为.pth。如果您打包遇到任何问题,请评论区留言,我将乐于与您探讨。
4.3 效果验证
我们用修改后的权重替换原模型,在CIFAR-10测试集上进行预测,效果如下:
-
原始权重:模型按正常训练的逻辑分类,误判为狗的样本极少
原始权重预测
-
修改后权重:模型判别为狗的样本数量显著增加,我们成功通过修改权重,操控了模型的预测结果
手动修改权重后的预测
0x05 批量测试:不同增量的攻击效果
手动修改二进制流程繁琐、极易踩坑,我们可以直接用Python脚本完成bias的修改,安全又高效。我们测试了不同增量对模型预测的影响:
-
增量
0.1:对模型影响极小,分类结果几乎无变化增量:0.1
-
增量
1:模型开始出现明显的偏向,误判为狗的样本增多增量:1
-
增量
2:模型的偏向性继续增强增量:2
您可以根据自己的需求调整增量大小,实现不同强度的后门效果。
0x06 代码地址
完整的自动化修改脚本、测试代码已上传至github,可自行下载体验。
https://github.com/wml1001/model-backdoor
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:十月的进阶之路 十月的进阶之路 十月的进阶之路《【AI安全】零训练成本到模型后门植入》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论