引子
被损坏的PNG图片:
仅仅被修改了一个byte,图片就损坏了。
开始分析
没有搞过这种分析,所以就按照文档一点一点来。装好WINHEX就开工了。
数据块:
名称 | 字节数 | 说明 |
---|---|---|
Length(长度) | 4字节 | 指定数据块中数据域的长度,其长度不超过(231-1)字节 |
Chunk Type Code(数据块类型码) | 4字节 | 数据块类型码由ASCII字母(A-Z和a-z)组成 |
Chunk Data(数据块数据) | 可变长度 | 存储按照Chunk Type Code指定的数据 |
CRC(循环冗余检测) | 4字节 | 存储用来检测是否有错误的循环冗余码 |
PNG文件署名域
8byte89 50 4E 47 0D 0A 1A 0A
每个PNG图片开头8个byte都是这一串。
固定文件头 IHDR
13byte
域的名称 | 字节数 | 说明 | 数据 |
---|---|---|---|
Width | 4 bytes | 图像宽度,以像素为单位 | 0x034e |
Height | 4 bytes | 图像高度,以像素为单位 | 0x047f |
Bit depth | 1 byte | 图像深度:索引彩色图像:1,2,4或8灰度图像:1,2,4,8或16真彩色图像:8或16 | 0x08 |
ColorType | 1 byte | 颜色类型:0:灰度图像, 1,2,4,8或162:真彩色图像,8或163:索引彩色图像,1,2,4或84:带α通道数据的灰度图像,8或166:带α通道数据的真彩色图像,8或16 | 0x04 |
Compression method | 1 byte | 压缩方法(LZ77派生算法) | 0x00 |
Filter method | 1 byte | 滤波器方法 | 0x00 |
Interlace method | 1 byte | 隔行扫描方法:0:非隔行扫描1: Adam7(由Adam M. Costello开发的7 遍隔行扫描方法) | 0x00 |
文本信息数据块 tEXt
71byte
信息内容:
Funny how one single corrupted byte can render the whole image useless.
图像数据块 IDAT
8192byte
图像数据块 IDAT
4096byte
再往下就是一大堆IDAT数据块。
在这个地方我发现了问题所在,第二个数据块的大小是0x1000,我按照这个大小跳过了对应长度的byte之后,没有看到下一个数据块的开始,所以我断定,这个长度应该是有问题的。我重新查找了0x2000长度的数据末尾,发现是下一个数据块的起始,所以问题就在这个数据块的长度数据上,修改长度数据,图片恢复。
修复之后的PNG图片:
讨论
其实我一开始是准备大干一场的,因为我猜是某个数据块的数据出现了问题,需要结合CRC验证来暴力破解。搞出来了才发现,原来是长度错误导致后面全面崩盘,才大半个图片都看不到了。本来是打算用python写个脚本自动找的,结果人肉解决了,有点尴尬的。
隐写
PNG图片里面的两个文本区域是天然的数据隐藏地点,但是很容易被发现,不够隐蔽。
从PNG图片的结构上来说,连续且大量的IDAT数据块是隐藏数据的好地方,每个数据块的长度其实是不定的,可以把数据隐藏在数据块长度的4byte上,用不同长度的数据块来隐藏数据。
还有图像透明数据块和数据点也可以隐藏数据,但是会导致图片失真。
2 条评论
看不懂系列
大佬又在说笑了