12

隐写技巧——PNG文件中的LSB隐写

 3 years ago
source link: https://3gstudent.github.io/3gstudent.github.io/%E9%9A%90%E5%86%99%E6%8A%80%E5%B7%A7-PNG%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84LSB%E9%9A%90%E5%86%99/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

0x00 前言

上篇对PNG的文件格式进行了分析,介绍了如何在不影响PNG文件的正常浏览下将payload以辅助数据块tEXt的格式插入到PNG文件中。这次将要介绍一个在图像数据块IDAT下隐藏payload的技巧——LSB隐写

Alt text

图片引用自http://datagenetics.com/blog/march12012/index.html

0x01 简介


IDAT数据块

  • 储存图像像数数据
  • 在数据流中可包含多个连续顺序的图像数据块
  • 采用LZ77算法的派生算法进行压缩
  • 可以用zlib解压缩

zlib解压缩的python实现代码如下:

#! /usr/bin/env python
import zlib
import binascii
IDAT = "789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667".decode('hex')
result = binascii.hexlify(zlib.decompress(IDAT))
print result

引用自http://drops.wooyun.org/tips/4862

LSB隐写

  • LSB全称least significant bit,最低有效位
  • PNG文件中的图像像数一般是由RGB三原色(红绿蓝)组成,每一种颜色占用8位,取值范围为0x00~0xFF,即有256种颜色,一共包含了256的3次方的颜色,即16777216 种颜色
  • 人类的眼睛可以区分约1000万种不同的颜色
  • 这意味着人类的眼睛无法区分余下的颜色大约有6777216种
  • LSB隐写就是修改RGB颜色分量的最低二进制位(LSB),而人类的眼睛不会注意到这前后的变化
  • 每个像数可以携带3比特的信息

0x02 Python实现


关于LSB隐写在github上值得学习的项目:

https://github.com/RobinDavid/LSB-Steganography

https://github.com/cyberinc/cloacked-pixel

下面对cloacked-pixel进行测试

测试图片:

Alt text

源文件下载地址: http://www.easyicon.net/language.en/1119182-Enderman_Png_icon.html

python lsb.py hide big.png 1.txt 123456

参数说明:

hide:表示加密模式 big.png:待加密的png图片 1.txt:存放payload 123456:加密的密码

运行后生成图片big.png-stego.png

Alt text

分析一下加密图片big.png-stego.png的格式,使用上篇文章介绍的check.cpp

下载地址:

https://github.com/3gstudent/PNG-Steganography/blob/master/check.cpp

加密前后对比如图

Alt text

cloacked-pixel在加密的过程中会删除其他数据块,只保留关键数据块IDAT

使用HexEditorNeo查看加密图片也能印证我们的判断,如图

Alt text

注:

当然也可以通过阅读源码进行分析

python lsb.py extract big.png-stego.png 3.txt 123456

参数说明: extract:表示解密模式 big.png-stego.png:待解密的png图片 3.txt:存放导出的payload 123456:解密密码

如图,成功解密获得payload

Alt text

python lsb.py analyse big.png-stego.png 

参数说明:

analyse:表示分析模式 big.png-stego.png :待分析的png图片 运行后会对图像进行分析,将其分割成块,标记每个块的最低有效位

Alt text

这是加密前后分析对比图

Alt text

肉眼几乎无法分辨图片的差别,因为payload越短,分析图的差别就越小,这里我们可以借助软件帮助分析

工具名称:Stegsolve

下载地址:

http://www.caesum.com/handbook/Stegsolve.jar

环境搭建:

安装jdk,配置java环境

使用Stegsolve打开a.png,选择Analyse-Image Combiner,选择b.png

进行异或对比(XOR),如图,检测到细微的差异

Alt text

0x03 C++实现


Grant Curell分享了通过c++实现的方法,值得学习,所以在此对其介绍并进行测试

文章地址: http://www.codeproject.com/Articles/581298/PNG-Image-Steganography-with-libpng 作者:

Grant Curell

代码下载链接:

http://www.codeproject.com/KB/security/581298/PNG_stego.zip

测试环境:

Win7 X64

vs2012

1、 直接编译会报错

项目zlib可直接编译成功

编译项目libpng,错误如下:

fatal error C1083: Cannot open include file: 'zlib.h': No such file or directory

解决方法:

需要对项目添加include目录

右键-Property-VC++ Directories

选择Include Directories

Alt text

添加zlib-1.2.3,输入:

..\..\..\zlib-1.2.3;
Alt text

再次编译,报错如下:

fatal error LNK1181: cannot open input file 'zlib.lib'

解决方法:

需要对项目添加lib目录

选择Library Directories

添加zlib.lib,输入:

..\..\..\LIB Debug;

如图,编译成功

Alt text

Tips:

在Include Directories和Library Directories中也可以直接指定绝对路径(如C:\test\cloacked-pixel-master\PNG_stego\zlib-1.2.3),本例使用..\表示的是相对路径

编译项目PNG_encode_decode,发生同样的编译错误

解决方法:

Include Directories下添加zlib-1.2.3和libpng-1.2.37-src,输入:

../zlib-1.2.3;../libpng-1.2.37-src;

Library Directories下添加libpng.lib,输入:

..\LIB Debug;

如图,最终编译成功

Alt text

注:

三个项目工程存在前后的调用关系,所以编译顺序为zlib-libpng-PNG_encode_decode

2、 加密测试

待加密文件:big.png

payload文件:1.txt

输出加密文件:bigen.png

项目PNG_encode_decode中的main.cpp修改如下:

#include "PNG_file.h"
void main() {

	PNG_file link = PNG_file("big.png");
	link.encode("1.txt");
	link.outputPNG("bigen.png");
}

运行后生成bigen.png,如图

Alt text

对比加密前后的文件,大小存在差异,如图

Alt text

原理上LSB隐写不会改变文件大小,查找原因

使用check.cpp解析数据块目录,发现加密后多了数个tTXt段

Alt text

使用HexEditorNeo查看加密图片细节,如图

Alt text

加密后的图片包含了原图片的一些信息,造成了图片大小不同

3、 去掉多余信息

方法a:

使用HexEditorNeo直接删除多余信息

方法b:

使用compress.cpp

下载地址:

https://github.com/3gstudent/PNG-Steganography/blob/master/compress.cpp

生成去掉多余tTXt段的加密图片bigensimple.png,如图

Alt text

bigensimple.png同原图片大小相同,如图

Alt text

4、 解密测试

项目PNG_encode_decode中的main.cpp修改如下:

#include "PNG_file.h"
void main() {

	PNG_file link = PNG_file("bigensimple.png");
	link.decode("2.txt");
}

运行后生成2.txt,获得存储加密后的payload

(5) 分析

对于LSB隐写,可使用Stegsolve辅助分析

打开加密图片后,选择Analyse-DataExtract

Bit Planes 选中Reg、Green、Blue的第0位

Bit Order选中LSB First

Bit Plane Order选中RGB

可以看到加密形式的payload,如图

Alt text

注: 当然可以通过阅读程序源码找到图片的加密数据,本例只是给出对图片分析的一些参考思路

0x04 小结


本文分别介绍如何通过Python和C++实现对PNG文件的LSB隐写,参照文中的分析思路也可对常见的LSB隐写数据进行提取分析。

注:

修改好的PNG_stego工程已上传至github:

https://github.com/3gstudent/PNG_stego-test

更多学习资料:

https://github.com/fgrimme/Matroschka

https://waronpants.net/article/png-steganography/

https://waronpants.net/pngsteg/trunk/steg.c

http://www1.chapman.edu/~nabav100/ImgStegano/

http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1

https://www.w3.org/TR/PNG/


LEAVE A REPLY


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK