图片藏文件的实现及原理

无意中看到了这个,虽然很早之前就已经用烂了,但是我也只是略懂怎么回事而已,今天就好好深入挖掘下吧
也许…老司机发车必备吧….

尾部追加法

这是最简单的一种方法,当然藏个小文本、种子之类的还是挺好的,不要想藏个病毒了,稍微有点电脑基础就能分辨出来;

先来说个例子:现在有两个文件,1.jpg2.zip,现在要把2.zip文件藏在1.jpg这张图里,并且要可以查看,只需要进入cmd进入到当前目录执行:copy/b 1.jpg+2.zip 3.jpg
这样就会得到3.jpg这个图片文件,可以正常查看,大小是两个文件的之和,如果用压缩软件打开这个文件(改个后缀也可以,用rar直接打开也可以)就会看到2.zip里的内容。
至此,老司机就可以去发车了。最好使用“最大压缩”的选项。

部分测试结果:
把ZIP和RAR文件添加到JPG/BMP/GIF/PNG,没有问题,全部可以实现。
把TXT添加到图像格式里,用记事本打开,在乱码的最后能隐约看到原来文件的样子,英文都能看到,中文全是乱码。
把ZIP/RAR添加到PDF里,也能通过。
把 ZIP/RAR添加到MP3/WMA/MID里,添加完后的音频不受影响,但ZIP/RAR打不开了,没有意义。
别的格式没有多试。

下面说原理

copy/b的作用是把两个文件首尾接起来,串个串。一般情况下,这样会破坏2个文件,造成无法读取,其实,能不能读全看程序怎么处理文件和文件本身的格式。
有人说是因为图像格式的文件大小定义在头部,而RAR格式的文件大小定义在尾部,所以2个文件共存才没有冲突。不知道对不对,google一下,查了BMP的文件格式,BMP文件简单来说分4个部分,文件头+图像头+颜色表+数据区,具体格式在这里可以看到。文件头部分有bfSize是定义整个文件大小,就是从文件头开始到数据区结束的总大小,也就是说,超出这个偏移的数据对文件来说没有意义,读图的程序也不会去理会,程序只读取bfSize里定义的那么多数据,别的一概不管。
而RAR格式呢,由于是私有格式,我只能查到一点点信息,这里解释了一部分格式的定义,由此我的理解是RAR文件内部以区块为单位,数据以区块存储,区块数量和大小不定,但必须包含几个特定区块,用来保存基本信息,所有数据分段的保存在大量区块中,类似IP数据包,而每个区块有独立的大小定义以及类似链表的关联定义,每个区块的大小都可知且独立。这样推测WinRAR读取文件的过程是先查找,再验证,再读取,也就是说找到区块,读取大小和类型信息后把整个区块的数据读出来,而区块外,区块间的数据对WinRAR来说无意义。
这样就好解释之前的方法了,图像程序对于头部定义的大小之外的数据不管,WinRAR对于区块外的数据,也就是图像的数据不管,2个互相不管,各读各的,当然可以共存。推而广之,2种格式类似以上情况的都可以共存。

内容覆盖法

通常来说,图片文件都有包含2部分:文件头和数据区。而“内容覆盖法”,就是把要隐藏的文件,直接覆盖到图片文件的数据区尾部。比方说,某图片有 100KB,其中文件头占 1KB,那么,数据区就是 99KB。也就是说,最多只能隐藏 99KB 的文件。
切记:覆盖的时候,千万不可破坏文件头。文件头一旦破坏,这个图片文件就不再是一个合法的图片文件了。
使用这种方法,对图片文件的格式,是有讲究的——最好用24位色的 BMP 格式。为啥捏?一来,BMP 格式本身比较简单,数据区随便覆盖,问题不大;二来,24位色的 BMP 相对其它的格式 BMP,文件尺寸更大,可以隐藏更多内容。

处理步骤

这种方法当然是不能和上面那样一句命令就能完成的,需要一些专用工具,或者可以写个Py脚本,很简单,有点编程基础的就可以看懂.
如下代码没有严格计算 BMP 的文件头尺寸,俺只是大致预留了 1024 字节,感觉应该够了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import sys

def embed(container_file, data_file, output_file) :
container = open(container_file, "rb").read()
data = open(data_file, "rb").read()

if len(data)+1024 >= len(container) :
print("Not enough space to save " + data_file)
else :
f = open(output_file, "wb")
f.write(container[ : len(container)-len(data)])
f.write(data)
f.close()

if "__main__" == __name__ :
try :
if len(sys.argv) == 4 :
embed(sys.argv[1], sys.argv[2], sys.argv[3])
else :
print("Usage:\n%s container data output" % sys.argv[0])
except Exception as err :
print(err)

提取方法

如果是藏的压缩文件,直接用rar打开即可,文件大小还不会发生变化哦
不过由于隐藏的文件覆盖了数据区,因此,图片在显示的时候,会有一块区域变成灰蒙蒙的(如果遭遇“肉眼审查”,可能会引起怀疑)

隐写术

这是一种比较高级的方法了,搞信息安全的可能比较熟
此方法会涉及较深奥的技术领域,本人实在能力有限。通俗地说:如果把图片的某个像素的颜色,进行微小的调整,肉眼是看不出来的;因此,专门的软件,利用某些高深的算法,就可以在变化的像素中隐藏信息。
有兴趣的同学,可以看“这里”的介绍;

处理方法

这种方法一般也只能用专门的软件了;使用这种方法,你需要用专门的工具来进行信息的隐藏和提取。在进行隐藏时,你除了指定图片文件和被隐藏的文件,还需要设置一个密码。隐写工具会把你的隐藏文件先加密,然后再进行隐写;提取的时候,需要用同一款隐写工具进行提取,并输入同样的密码,才能提取出来。
假如图片文件落入攻击者手中,他必须同时知道2个信息(你用哪款隐写工具,你隐写时设置的密码),才有可能破解出隐含的信息。因此,安全性相当高。

名称类型界面
Silent Eye开源图形界面
Steg Hide开源命令行界面
Ultima Steganography商业图形界面

这种方法虽然隐蔽性和安全性都很高,但是只能隐藏较少的信息(此方法能隐藏的信息量,和图片面积有关,和图片格式无关。比如一张 1600*1200 尺寸的,无论哪种格式,大约只能隐藏 几KB 的数据)

参考

http://blog.fulin.org/2006/11/simple_hide_file/
https://program-think.blogspot.com/2011/06/use-image-hide-information.html
https://zh.wikipedia.org/wiki/%E9%9A%90%E5%86%99%E6%9C%AF

喜欢就请我吃包辣条吧!

评论框加载失败,无法访问 Disqus

你可能需要魔法上网~~