FrancescoPaoloL/imgpoison

GitHub: FrancescoPaoloL/imgpoison

一款用 C 语言从零实现的图像隐写术学习工具,支持 LSB 和扩频两种方法,用于研究隐藏文本在图像中的嵌入与检测,特别关注 payload 在多模态 AI 系统中的存活能力。

Stars: 1 | Forks: 0

# imgpoison 一款使用隐写术将文本隐藏在图像中的命令行工具。 处理后的图像看起来与原图毫无二致——隐藏的文本肉眼不可见 并且能够经受住 JPEG 压缩。 **这是一个学习项目。** 旨在从基本原理出发理解隐写术 并探索 LLM 安全概念。非生产就绪,未做优化,也未进行加固。 ## 为什么做这个 研究隐藏的 payload 如何在图像处理流程中存活——具体来说,就是探究 嵌入图像中的提示注入在经历 JPEG 压缩、缩放或重新编码后, 是否仍能影响多模态 AI 系统。 ## 方法 **LSB** (最低有效位) —— 翻转每个像素的最后一位来编码数据。 速度快且容量大,但非常脆弱:JPEG 压缩会破坏 payload。 仅适用于无损格式 (PNG)。 **SS** (扩频) —— 使用伪随机 chip 序列将 payload 信号分散到数百个像素中。 能够在 JPEG 压缩后存活。需要一个 seed(密钥)来嵌入和提取。 ## 构建 ``` sudo apt install libjpeg-turbo8-dev make ``` 依赖项:zlib, libjpeg-turbo, libm。没有使用 libpng —— PNG 编解码器是手工编写的。 ## 用法 嵌入: ``` ./bin/imgpoison --embed --method ss --seed 42 --payload "text" input.png output.jpg ``` 提取: ``` ./bin/imgpoison --extract --method ss --seed 42 output.jpg ``` LSB 嵌入(仅限 PNG): ``` ./bin/imgpoison --embed --method lsb --payload "text" input.png output.png ``` 检测 LSB 嵌入: ``` ./bin/imgpoison --extract --detect input.png ``` 分析 —— 检查图像中是否存在隐藏的 payload 而不将其提取出来: ``` ./bin/imgpoison --analyze --method ss --seed 42 output.jpg ./bin/imgpoison --analyze --method lsb input.png ``` SS 分析需要使用与嵌入时相同的 seed。它会打印每个 header 位的关联 强度及结论。LSB 分析会对像素值分布运行卡方检验。 ## 参数 | 参数 | 默认值 | 备注 | |--------------|---------|----------------------------------------------| | --seed | 42 | 嵌入和提取的密钥 —— 必须匹配 | | --strength | 10 | 信号强度。越高 = 越稳健,但也越明显 | | --method | lsb | lsb 或 ss | ## STRENGTH 权衡 | STRENGTH | 相对 JPEG 噪声的 SNR | 可见吗? | 能在 q95 压缩下存活吗? | |----------|-------------------|----------|---------------| | 3 | ~96:1 | 几乎不可见 | 是 | | 10 | ~320:1 | 略微可见 | 是 | | 20 | ~1280:1 | 是 | 是 | ## SS 的工作原理 每个 payload 位都被隐藏在两组像素(块 A 和 块 B)中。 块 A 稍微变亮一点,块 B 稍微变暗一点(或反之)。 提取时:比较 A 和 B —— 较亮的那一个就编码了该位的值。 JPEG 会给像素添加随机噪声,但由于噪声对 A 和 B 的影响是同等的, 在将两者相减时噪声会被抵消。信号从而得以保留。LSB 无法存活的原因是 JPEG 会使用于存储数据的精确位随机化。 seed 控制着一个伪随机序列 (chip),用于打乱所使用的像素及其方式。 没有 seed,就无法进行提取。 ## 工具 **diffmap** —— 可视化原图与隐写图像之间的差异。 有助于验证嵌入是否正常工作。 ``` python tests/diffmap.py img/original.png img/stego.jpg ``` 需要关注的特征: - SS → 整张图像均匀分布着椒盐噪声(信号散布在各处) - LSB → 左上角有一小块明亮区域(payload 集中在开头) **test_robustness** —— 测试 payload 在图像变换中的存活情况。 ``` python tests/test_robustness.py ``` 使用默认设置 (STRENGTH=10, CHIP_SIZE=256) 的结果: | 变换 | 结果 | |------------------------|--------| | baseline | PASS | | recompress q90 | PASS | | recompress q85 | FAIL | | recompress q75 | FAIL | | rotate 1 degree | FAIL | q85 及以下的压缩会在 STRENGTH=10 时超过噪声阈值。 增加 --strength 可以提高稳健性,但代价是可见性增加。 ## 待办事项 - Shell 脚本回归测试(嵌入 → 提取的完整往返测试) - LLM 安全视角的文档 - 修复 --analyze 中的强度估算(目前因 JPEG 噪声而被放大) ## 参考 Marvel, Boncelet, Retter —— Methodology of Spread-Spectrum Image Steganography, ARL-TR-1698, 1998. apps.dtic.mil/sti/citations/ADA349102 Press, Teukolsky, Vetterling, Flannery —— Numerical Recipes in C, 2nd ed., 1992. LCG 常量(乘数 1664525,增量 1013904223)来自第 7 章。 Knuth —— The Art of Computer Programming, vol. 2, sec. 3.4.2. Fisher-Yates 洗牌算法实现。 ITU-R BT.601 —— 亮度系数参考。 en.wikipedia.org/wiki/Luma_(video)#Rec._601_luma_versus_Rec._709_luma ## 与我联系 [LinkedIn](https://www.linkedin.com/in/francescopl/) · [Kaggle](https://www.kaggle.com/francescopaolol)
标签:AI安全研究, DNS 反向解析, LSB隐写, 信息隐藏, 图像处理, 图像隐写分析, 图片木马, 多媒体安全, 多模态AI, 客户端加密, 对抗性机器学习, 扩频技术, 抗压缩隐写, 提示注入, 搜索语句(dork), 数字水印, 数据隐藏, 网络安全, 隐写术, 隐私保护, 集群管理, 鲁棒性分析