jpg图种

图种


图种的定义是采用特殊方式将 jpg 图片文件和 rar 压缩文件合并起来、表面上看无法发现隐藏的 rar 文件的图片

名字"图种"貌似源自此方式有利于某些网友(老司机)传播种子文件

通常将图片的后缀名修改为 rarzip,解压就能获得其中隐藏的文件


原理

jpg 图片文件有其特有的文件格式,其中一点是:在十六进制查看器中,正常的jpg 文件以 FF D8 开头,以 FF D9 结尾

Notepad++十六进制查看器

网络上最常用的十六进制查看器是WinHex和010 Editor,但两者都需要收费;事实上Notepad++可以通过添加插件,进行十六进制查看(虽然不能导出)

  1. 插件 → 插件管理 → 可用 中如果能看到 HexEditor,就将其打勾,重启Notepad++

  2. 但如果 可用 中未找到 HexEditor,需要前往作者GitHub:https://github.com/chcg/NPP_HexEdit/releases,下载对应版本的 HexEditor.zip,解压得到 HexEditor.dll

/Notepad++/plugins 目录中,新建一个 HexEditor 文件夹,然后将 HexEditor.dll 放入其中,重启Notepad++

事实上,新版Notepad++已经去掉了HexEditor在线插件功能,只能使用自定义插件

尝试

在Notepad++中新建空白文档,敲入 Hello World,然后点击 插件 → HEX-Editor → View in HEX,可以得到 48 65 6c 6c 6f 20 57 6f 72 6c 64

其中 48 就是 H 的Unicode十六进制编码、20 是空格的其中一种Unicode十六进制编码

警告

Notepad++十六进制插件的复制功能有bug,会将 00 复制为 20

随便用Notepad++打开一张 jpg 图片,看到乱码:

打开Notepad++的十六进制查看功能:

这时可以看到十六进制下查看的 jpgFF D8 开头:

FF D9 结尾:

能够在 jpg 图片文件中隐藏信息,利用的是图片查看器只读取 FF D9 之前的数据,并将这段数据显示为图片,这也意味着 FF D9 之后的数据不会以图片的形式出现

于是在 FF D9 之后的位置就可以存放我们要隐藏的数据了

为什么是 jpg ?

因为 jpg 有文件结束标识 FF D9,其它格式的图片文件只有文件头标识,如

  • GIF 文件头标识:47 49 46 38 39(37) 61
  • ICO 文件头标识:00 00 01 00 01 00 20 20

能够用作图种的还有 png 格式,它的IEND Chunk可以充当文件尾标识(在另一篇文章中详解)

【本部分参考】

博客文章 https://www.cnblogs.com/plf112233/p/3544547.html


制作

我们可以自己制作一个图种

首先创建一个 flag.txt,将其压缩成 flag.zip,然后找一张 jpg 格式的图片 temp.jpg

在Win10 cmd窗口下执行指令:

1
copy /b temp.jpg+flag.zip output.jpg

执行完上述指令后,就能在目录中得到我们隐藏 zip 文件的图种—— output.jpg

copy命令

cmd下的一个命令,用于复制文件(区别于Linux下的cp命令)

基本用法:copy 源文件 目标路径

copy d:\test\test.txt d:\表示将 test.txt 文件复制到D盘根目录下

copy 指令是cmd自带的,可以通过 copy /? 来查看它的各个参数:

copy 除了复制外,还能够合并:将多个待合并文件用 + 连接即可

命令 copy /b temp.jpg+flag.zip output.jpg 通过前置的 /b 参数,指定操作的都是二进制文件;然后 copy 会以二进制的形式将 temp.jpgflag.zip 合并,并导出为 output.jpg

output.jpg 是一张看上去与 temp.jpg 一样的图片


检测

如何检测是否有隐藏的文件呢?

  • 十六进制查看器

    对于 jpg 图片文件,用十六进制查看器打开 jpg 图片,检查是否以 FF D9 结尾,如果不是,那么很有可能有隐藏数据

  • binwalk

    binwalk工具主要用于路由器逆向分析,但它也常用在分析隐写文件(我们只用它的最基础用法)

    其原理就是检索匹配文件头,常用的一些文件头都可以被发现

    安装

    在Linux中,执行命令:

    1
    >$ sudo apt install binwalk

    即可安装成功

    如果安装失败,不妨升级 apt : $ sudo apt-get update

    • 对于普通的 jpg 图片文件,binwalk的分析结果类似:

    • 而对于我们制作的隐藏 zip 文件的图种,binwalk会显示:

      它告诉我们,在图种的数据中,偏移量从 59863039448114 是一个 zip 文件

    • 如果是一张 png 图片隐藏在 jpg 图片文件中,那么会显示:

    使用binwalk不止可以查看隐藏的 zip ,还能查看 pngtxt 等格式文件

    file

    file命令用来查看文件类型

    binwalk不同,binwalk会扫描整个文件,对比各文件头标识,能够分析出文件中的其它隐藏文件;而file会结合整个文件的数据,辨别出该文件的类型

    file不能用于发掘潜藏在文件中所有可疑的文件类型,但它通常用于判断未知文件

    在CTF中,往往会得到一个未知后缀名的文件,如 1.hahaha;甚至没有后缀名: 2,这时候执行命令:

    1
    2
    >$ file 1.hahaha
    >$ file 2

    会显示它最有可能的文件类型:

    • 可能是毫无意义的 Data
    • 可能是编译后的 pyc 文件
    • 可能是一张 gif 图片

    得知它的文件类型后,将后缀名更改回正确的即可正常打开


分离

  • 强行更改后缀名

    如果 jpg 图片中隐藏的是压缩文件,那么将 jpg 文件的后缀名直接更改为 rarzip ,再进行解压,是能够获得隐藏压缩文件的内容的

  • binwalk

    binwalk %File_Name% 命令能够通过扫描发现目标文件中所有可识别的文件类型;扫描出来后,添加 -e 参数--extract 参数,binwalk会生成一个 _%File_Name%_extracted 目录,目录中存放着所有可能提取出来的文件

    binwalk是按照定义的配置文件中的提取方法从固件中提取探测到的文件

    以我们之前制作的图种为例:

    执行命令:

    1
    $ binwalk output.jpg -e

    能够观察到目录下生成了一个 _output.jpg.extracted 目录,里面有一个 flag.txt 文件,以及一个包含 flag.txt 但被重命名为 3DAA.zip 的压缩文件

  • foremost

    foremost是Kali Linux提供的一款还原专用工具,它基于

    • 文件开始格式
    • 文件结束标志
    • 文件内部数据结构

    ,同镜像文件的数据进行比对,来还原文件

    有时binwalk无法正确分离出文件,这时候可以使用foremost !!!

    -t :指定文件类型

    -i:指定扫描文件的分区

    -o:指定恢复文件存放目录,必须是空目录

    仍然是我们之前制作的图种作为例子,执行命令:

    1
    $ foremost output.jpg -o temp

    随后在 output.jpg 所在的目录会生成一个新目录 temp,里面包含 output.jpg 导出的文件:一张 jpg 文件、一个包含 flag.txtzip 压缩文件和一个 audit.txt 记录文档

    记录文档 audit.txt 记录了操作文件、操作时间、文件大小、导出文件的类型数量等信息

  • Linux dd 指令

    dd 是Linux下用于读取转换输出数据的命令,主要参数有:

    • if:输入文件 (input file)

    • of:输出文件 (output file)

    • ibs:设置一次读入bytes个字节 (input bytes),即指定一个 blocks 为bytes个字节

      obs:设置一次输出bytes个字节 (output bytes)

      bs:同时设置读入/输出个bytes个字节

    • skip:从输入文件开头跳过 skip 个块后再开始复制(该参数用于提取)

    • conv:提供11种转换,举例有:

      • lcase:大写字符转换为小写字符

      • ucase:小写字符转换为大写字符

      • swab:交换输入的每对字节

        swab 貌似可以用于出CTF题目,中文经过 swab 会完全看不懂,英文只是每两个字母相互交换,包括 \n

    • --help:显示帮助信息

    • --version:显示版本信息

    尝试

    创建一个 temp.txt,写点英文句子,然后执行:

    1
    >$ dd if=temp.txt of=output.txt conv=lcase

    可以看到 output.txt 中所有大写字母都改小写了

    以我们之前制作的图种为例:

    通过binwalk查看 jpg 里面隐藏的 zip 文件的偏移量为 5986303,那么使用 dd 命令将 5986303 之后的数据提取出来:

    1
    $ dd if=output.jpg of=appear.zip bs=1 skip=5986303

    output.jpg 所在的目录会出现 appear.zip,解压会得到我们之前隐藏的 flag.txt

对比

binwalkforemost都是自动化分离工具,当binwalk无法正确分离时,可尝试使用foremost

dd是半自动化工具,有时自动化工具不能实现文件的分离,需要使用这个工具手动分离

练习一:NSCTF,下载 hacker.jpg

链接:https://pan.baidu.com/s/1STYlR0IB49kVM4pIKL8aKg
提取码:7i3m

练习二:下载文件 1.reverseme

链接:https://pan.baidu.com/s/1E0ObWe15QCDGvBADbfdP1g
提取码:codx

解答一:

binwalk发现有隐藏的 jpg 图片

分别尝试使用binwalkforemostdd来提取图片隐藏的信息,发现foremostdd能够成功获取,获得的图片就是flag

解答二:

莫名其妙的文件后缀 .reverseme,用file显示为 1.reverseme: data

Notepad++打开文件,显示乱码,转换为十六进制查看。发现文件头为 D9 FF,而文件尾为 D8 FF。由于 jpg 文件的文件头为 FF D8,文件尾为 FF D9,因此猜测整个文件按照bytes进行了翻转。写一个脚本将它还原:

1
2
3
4
with open("1.reverseme", "rb") as f:
with open("temp.jpg", "wb") as g:
g.write(f.read()[::-1])
# "rb"、"wb"指的是将数据由字符串转换为bytes进行处理,恰好是我们要翻转的一个字符的十六进制表示

打开生成的 temp.jpg,得到左右翻转的flag图片,随便找个办法翻转回来就行了

【本部分参考】

HexEditor下载来源 CSDN博客 https://blog.csdn.net/PYTandFA/article/details/83004124

菜鸟教程 Linux dd命令 https://www.runoob.com/linux/linux-comm-dd.html

云社区 文章 https://cloud.tencent.com/developer/article/1419453

简书 文章 https://www.jianshu.com/p/02fdd5edd9fc


总结

图种利用的是 jpg 存在文件尾标识 FF D9,标识之后的数据都不会被图片查看器显示,因此能够将数据隐藏在图片中