1.图片的LSB隐写

LSB,即Least Significant Bit,最低有效位。

LSB隐写的大致思路就是通过更改文件里的最低有效位,在尽少影响文件的情况下隐秘地写入信息

最常见的方式是在图片中隐写信息,如文本

图片由像素构成,常见的颜色通道是(A)RGB

那么我们可以在每个颜色的最后一位动点手脚,反正不是0就是1,要么增或减1,要么就完全没变

可以让255变成254,或者就根本不变。一个单位的差距,人类肉眼凡胎实在难以察觉。考虑到实际,不同显示器也有色差,色域或其它的不同,这点问题可以直接让颜色最低位的改变带来的影响微乎其微

借此,我们就可以把文本按bit拆分,写入到每个颜色里的最后一位。然后读取的时候按同样的规则把bit拼接起来就能得到原文,没意识到图片被动手脚的人自然难以发现异常

但需要注意的是,隐写需要保证数据不被破坏,所以不能使用JPG隐写,JPG使用了有损压缩。但例如PNG使用无损压缩,BMP根本就不压缩

mc加光影好看

让我们在这个PNG文件里面隐写"Herobrine"进去如何?

我在这里找到了可用的隐写程序。这部分我被AI卡了好几天,因为它写不出能找到隐写内容的程序。。。

程序和使用方式我就不复制出来了

cmd
output

果然是一点区别都没有(看起来)

1
2
9b5fb0f424711f9a3651ecfb37763750    #input
31d2118725c3f3bc4ef63ea450f2d7a3 #output

但是MD5不会骗人,这说明两张图片并非一个文件

接下来就使用Stegslove打开output.png,点击Analyse-Data Extract,如图中勾选,点击Preview

Stegslove

看,起头的文字是什么?就是我们想要隐写的"Herobrine"很有八年前看mc都市传说的感觉

对于BMP的LSB隐写也是一样的操作,连程序都不用换

2.接续式的文件隐藏

在网上没有找到这种隐写方式有什么特定的称呼,我就暂且起这个名

这个方法其实很简单,用的特性就是压缩软件会自己在文件中寻找zip的文件标识并且忽视其他部分

例如我们把最上面的png文件(input.png)做一个副本后用wxMEdit打开,再选择你想隐藏的zip文件,同样用wxMEdit打开(这里我选择上次使用过的hello.zip)

input - 副本.png
hello.zip

这里我们直接选中hello.zip的窗口,CTRL+A,CTRL+C带走,转到input - 副本.png的窗口,找到最后的地方,直接CTRL+V拼接进去

CRTL+S保存,大功告成

这个步骤其实也可以用一个cmd命令完成

1
copy /b <file1>+<file2> <file3>

意思就是在二进制的方式下把file2的内容接续进file1以此生成file3

所以这一个步骤就可以写成

1
copy /b input.png+hello.zip <custom_name>.png

这时候用图片查看器查看图片仍然是看不出区别,甚至可以说看起来根本没变化

input - 副本.png

但有趣的是,如果我们把后缀名从png改成zip,它会变成可读的压缩文件,并且文件与原本的压缩包一模一样

input - 副本.zip

当然拼接后文件大小理论上是两者之和。所以如果一个图片有几百MB甚至上GB那基本就是有问题(分辨率超级超级高应该不常见)

但像现在的情况就是一个文本的压缩包能有几个大小?根本不可能从大小判断

怎么寻找它的隐写内容?

这次我们使用的隐写载体是PNG,在一般情况下,PNG一定会以0x[00 00 00 00 49 45 4E 44 AE 42 60 82]结束,那么我们就查找这一块,看看这部分后面还有没有东西

显然是有的(你看里面还有"IEND"这几个字)。PNG文件内容到这十二个字节就是结束,这之后还有只能说明这个文件里不止有这个PNG。

对不同类型的隐写载体我们自然要使用对应的结束表示来寻找

但像BMP这种没有结束标识的文件就比较难搞,我们只能通过图片宽高等信息来判断图片结束位置,再看后面有没有东西

在这12个字节之后,后面4个字节是0x[50 4B 03 04],这是zip压缩源文件数据区的标识段,我们便可以猜测这剩下的部分是zip文件

所以我们就可以把这剩下的部分复制走制作一个新文件,用压缩软件打开,正好我们就可以看见一个完整的压缩包内容。

那如果对方不讲武德不放在最后而是放在最前或者是中间呢?我试验过了,这样子做会让图片无法打开所以没有意义。

实际上这种隐写方式适用于大多数类型文件里面隐藏zip,甚至是编程作业的exe(正经的不知道,毕竟真的不好验证是否影响功能)。就很神奇,大部分文件只会根据文件信息读取属于自己的数据块,但起始信息一定要处于文件开头。但zip读取的时候它对应的数据块可以是在文件的任何地方

但实际上这种方式可以隐藏任意文件,以zip示例的原因只是它就算被隐藏了也能打得开,其他类型则不一定

只要能看出表文件的结尾后面还有没有东西我们就可以看出它有没有隐藏别的文件

(或许会再更新)