课程名称:
053-使用C语言实现LSB图像信息隐藏
课程分类:
信息隐藏
学分:
1
最小学习时间(分钟):
5
完成学习时间(分钟):
40
知识点:
实验等级:
中级
任务场景:
小王接到磐云公司的邀请,对其公司旗下社交媒体网站进行白盒渗透测试,小王发现在网站用于上传图片的文件夹中存在大量隐藏恶意代码的图片,对图片进行分析发现这些图片木马利用了新型隐写术来躲避常规检测工具的检测,故管理员很难察觉。小王与管理员沟通后,复现了利用隐写术进行恶意代码利用的场景,以此告知管理员此类文件的危害。
任务分析:
互联网上的服务器无时无刻不在对用户上传的数据进行处理,数据处理不当将导致公司面临巨大的损失,特别是在服务器没有专门为上传的数据进行安全校验的情况下,恶意行为者可以使用隐写术工具来隐藏部分软件的恶意代码,实现在网站上托管图像,或通过电子邮件发送提供恶意JavaScript的图像。隐写术在渗透测试中最主要的应用是对Payload进行隐藏,本次实验将会对PNG的文件格式进行分析,编写C程序实现自动解析文件格式,并依照文件格式添加自定义的Payload,且保证图片的正常浏览的同时Payload程序同样能够成功被执行。
预备知识:
理解隐写术
数字隐写术(Steganography)是一种可以隐藏代码的技术。例如将某个文件、信息、图像或者视频隐藏在另一个文件、信息、图像或者视频中的技术。通常该技术也被称之为“Stego”,是指在其他非秘密文本中,或者叫“载体”信息内隐藏消息或信息的做法。同时也意味着恶意行为者可以将恶意代码隐藏在.jpg\.png\.bmp\.gif或其他图像文件格式内。在信息安全中,隐写术也是举足轻重的一块领域,他是一种混淆的方法,与密码学完全不同的是,密码学是编制编码或者对加密信息的实践:例如有这样一段加密的信息,能够很明显地看出他隐藏了某些内容,这些信息通常看起来没有任何逻辑的一段字符串,需要采用专业的方法来进行解码或解密。
低调但有效的隐写技术虽然是旧把戏,但将代码隐藏在看似正常的图像中,还是可能逃脱许多网络安全人员的法眼。
数字隐写类型
数字隐写的类型可以分为文字、图像、音频和视频隐写。
这里提到的文字隐写是迄今为止最早和使用难度相对较高的一种。他通过自然语言隐藏密码信息。由于在文本文档中缺乏冗余,文本隐写术具有挑战性。音频隐写通过以人类不可察觉的方式来修改音频信号的频段发送隐藏的信息,并将密码消息作为噪声嵌入到在人类听觉范围之外的频率的音频文件中。例如,频谱隐写术通常用于通过无线电波发送隐藏的消息。类似地,在视频隐写术中,秘密消息隐藏在视频流中。
数字信息的隐藏方法有很多种,主要分为两大类。
插入:通过插入方法隐藏信息会插入一些额外内容,除了被隐藏的信息外,还有文件制作工具的标识,这个标识记录了隐写程序处理隐藏载荷的地点。这种方法通常会利用文件格式中的空白。
替换:通过替换方法隐藏信息会改变信息中的字节或者交换字节顺序。他不会在载体文件中增加任何新的内容,而是通过修改字节位置让人们看不到或者听不到文件内容。例如,LSB(Least Significant Bit,最低有效位)替换方法,就是使用隐写程序修改文件中每个字节的最低有效位(将1变成0,0变成1)。
理解LSB隐写
LSB全称是leastsignificant bit,最低有效位。下面要讲到的图像隐写是数字隐写术中最为常见的形式,即使用图像作为载体。要充分的了解基于图像的隐写术,我们首先要理解数字图像的概念——由8位或者24位颜色组合而成,每个像素通常由黑白图像的8位(1字节)组成或彩色图像的24位(3个字节)即它是由红蓝绿组成(通常称之为RGB格式)取值为0x00~0xFF,即为256种,一共包含了256的三次方中颜色,即16777216中颜色。例如RGB(166,148,230)则表示R = 10100110,G = 10010100,B = 11100110。
但是人眼能够分辨的大概1000万种不同的颜色,大多数颜色都可以通过三原色的不同比例调剂出来。还有很多种颜色的细微差别的变化人类的眼睛是察觉不到的。这也就意味着人类的眼睛无法区分余下的颜色大概有6777216种,LSB隐写就是修改RGB颜色分量的最低二进制(LSB),而人眼不会注意到这前后的变化。
这种隐藏方法通过普通的手段几乎是检测不到的。通常只有通过统计分析方法才能将其以独立的形式被检测到。下面两张图对比了修改LSB后的图像产生的颜色变化,肉眼几乎察觉不到二者的不同之处。
通过文件文件很重最低有效位传递信息提供了一个存储信息的隐藏方法,而且还不会改变文件大小。对比原始文件和修改后的文件可以发现文件被修改过,但前提是你手上有原始文件。
PNG文件格式
PNG图像格式文件由文件署名和数据块(chunk)组成。
文件署名域
前8字节是PNG文件署名域用来识别该文件是不是PNG文件。该域的值
事实上,所有的文件都是以二进制的形式进行存储的,本质上没有差别。之所以使用的方法不同,只是因为我们理解他的方式不同。在每一个文件(包括图片,视频或其他的非ASCII文件)的开头(十六进制表示)实际上都有一片区域来显示这个文件的实际用法,这就是文件头标志。
Linux下我们可以用file命令直接查看文件的实际格式,但是他本质上也是利用文件头标志来进行文件类型判断的。下面就简要介绍下手动判断PNG\JPG\BMP\GIF等文件真实类型的方法。
通过这个表格,我们就可以通过检查文件的十六进制头来判断文件实际的类型了。具体查看的方法如下:
Windows中,我们可以通过Editplus之类的文本编辑器检查文件的十六进制表示,操作十分方便。
Linux中,我们可以通过hexdump命令来查看文件的十六进制形式,用这种方法查看png文件(路径为:/etc/alternatives/start-here-256.png)的结果如下:
但是这个工具只能查看不能对数据进行修改。实际上,此处显示的字节顺序跟机器是有关的,在常见的x86和常见的OS(如Windows,Linux,FreeBSD)s使用的是小端模式,因此他的高位是相反的,比如 5089 (16进制)那么高位字节就是89,低位是50,实际中按照日常的阅读习惯应该为
这样才是标准的PNG文件的头。
当然我们还有更方便强大的工具——VIM,用这个可以查看和修改文件的十六进制表示形式。我们用vim打开刚才的png文件,会用ascii形式表示:
接下来我们需要在命令行下输入:%!xxd,就会得到下面的展示形式:
还是非常方便的,而且高低位的位置与一般的显示一致。当我们需要返回ascii模式的时候,只需要输入:%!xxd -r即可返回之前的模式。
注意:在十六进制里我们可以通过编辑十六进制码来修改值,但是不要修改后面对应的ascii码和前面的地址,而且模式转换过去后一定要记得转换回来。
数据块
数据块类型
辅助数据块
任务实施:
053-使用C语言实现LSB图像信息隐藏
实验环境说明:
实验机:p100_win10-1(Windows 10)用户名:administrator 密码:123456
00:00:00
00:19:08
第一步,打开网络拓扑,启动实验虚拟机。
第二步,打开实验操作机器,点击桌面上的PentestBox快捷方式进入渗透测试工具集。并输入命令hexeditor调出工具:Hex Editor。
第三步,对桌面下隐写术Images中的LSB-File文件夹中名为start.png的图片进行分析,选择文件菜单栏,找到打开文件选项
选择桌面下的隐写术Images——LSB-File文件夹下的图片,点击打开文件(O)...打开图片start.png。注:案例中所有脚本文件都位于LSB-File目录下
第四步,使用快捷键shift+右方向键即可对该图片文件的16进制字符串进行标记,并找出文件署名域的字段信息,start.png文件前面8个字节为文件署名域,其固定格式为:89 50 4e 47 0d 0a 1a 0a
解读IHDR字段中的信息。其数据块结构我们把它划分为Length、Chunk Type Code、Chunk Data、CRC四个部分。
Length:前4个字节,作为定义长度的字段,00 00 00 0D十进制为13,代表长度为13个字节
Chunk Type Code:一共4字节,用于定义数据块类型码,此处为IHDR
Chunk Data:一共有13字节,用于定义数据内容
RC:共有4字节,对Chunk Type Code + Chunk Data做CRC32计算得出的值
即对上述中的49 48 44 52 00 00 00 1a 00 00 00 1a 08 04 00 00 00
第五步,通过编写程序对CRC算法进行验证,将其保存为CheckCRC.cpp,源代码如下
具体操作方法如下:
打开桌面上的VC6,然后在新打开的应用程序界面中选择文件(F)—新建(N)...
可以看到如下界面,选择文件选项,然后找到“C++ Source File”,对该程序命名
将源代码输入到VC++中,然后编译执行
运行后如图,输出03438445
同文件中的CRC32校验码进行对比发现二者的值相同
第六步,下一步继续在HexEditor中分析辅助数据块中的图像γ数据块——gAMA的值
数据块的结构如下
分析辅助数据块中的基色和白色度数据块——cHRM
cHRM数据块结构如下
中间的数据块还有IDAT、tEXt等就不详细进行分析了,我们着重分析一下它图像结束数据块——IEND
IEND数据块结构 | |
Length(0) | 00 00 00 |
Chunk Type Code | 49 45 4e 44 |
Chunk Data | null |
CRC | AE 42 60 82 |
固定结构,CRC的值为对Chunk Type Code作CRC32校验,如下图,我们继续使用前面编写好的CheckCRC.cpp来进行验证,仅需要修改如下截图部分的代码即可
运行得到CRC的结果为AE 42 60 82,验证结果与文件尾部的CRC值相同。
第七步,编写程序分析文件格式,这里我们需要用到的工具依然为VC6.0,下面我们来创建一个CheckPNG.cpp源码文件,便于我们更加系统的分析文件的格式。创建步骤同第五步
如下图所示,将程序按照EditPlus的格式输出,便于日后对格式进行分析
从第8字节开始,顺序来读前四字节为ChunkLength字段
那么对应的代码应该为
接下来的四个字节为ChunkName,使用printf将其打印
根据ChunkLength数据块长度值来读出完整的ChunkData,紧接着读出CRC32的值,并且与Chunk Type Code + Chunk Data所求出的CRC32校验值作对比,最后将其保存为CheckCompare.cpp,实现这一操作的完整代码如下
第八步,将C:\Users\Administrator\Desktop\隐写术Images\LSB-File\start.png复制到C:\test\下,并改名为00.png
在VC6.0中进行编译CheckCompare.cpp,然后运行编译后的程序,即可获得完整的PNG图片文件结构
可以看到与我们前面所分析的完全一致。我们通过这个程序实现对PNG文件进行格式分析,对PNG文件的数据块名词、偏移地址、数据块长度、比较预期和实际的CRC32校验码,并可以给予对批量文件进行分析,来查找出那些可能包含了恶意Payload的文件。
第九步,在前面我们提到了,这些辅助数据块的内容实际上对PNG图像的浏览是没有任何影响的,那么下面我们尝试去除PNG文件的所有辅助数据块看看图片还是否能够正常的浏览。下面的实验我们将使用Hex Editor来去除源数据中无关紧要的辅助数据块gAMA、cHRM和bKGD这一部分的内容。
操作步骤如下:首先在桌面上的PentestBox中输入hexeditor来打开软件,然后我们将下面的内容进行标记,在进行操作之前不要忘了,保存一下原版的png图片数据用于后面进行对比
使用快捷键Ctrl+x或者右键鼠标点击所选区域找到cut选项,删除辅助参数
修改完数据后,点击选项栏中的保存按钮来保存修改后的数据
下面,我们来对比修改数据的与未修改数据的PNG文件。发现文件大小发生了变化,但是不影响PNG文件的浏览。
第十步,下面我们要做的操作是通过程序来实现去除所有辅助数据块,仅保留关键信息。程序先对ChunkName作判断,并忽略非关键数据块(Ancillary Chunk)的信息,在实现该代码之前,我们需要将new.png移动到c:\test目录下,并改名为00.png,然后编译完成下面的完整代码:compress.cpp
通过VC6.0编译并执行程序Compress.cpp,结果如下
程序执行后PNG文件大小的变化,左边为原始的PNG文件大小,右边为去掉所有辅助数据块后的文件大小,且仍然可以浏览
第十一步,下面我们对经过Compress.cpp加工后的图片来手动添加payload。我们依照辅助数据块的格式来写入运行计算器程序(calc.exe)的Payload,首先我们需要通过Python来将calc.exe进行编码,将其转换为16进制形式。输入命令python,然后从binascii库中的导出ba模块用于转换,然后直接使用ba的方法:b=ba.b2a_hex(‘待转换的数据’),然后打印出b的值,操作如下
得到了calc.exe的16进制值,下面我们将其填充进辅助模块tExt中:
对应的tExt完整数据块结构如下
要写入的十六进制数据如下
第十二步,使用Hex Editor插入数据到C:\test\new.png中,修改之前先备份new.png为new_bak.png第十二步需要用到,如图所示,具体操作定位到预先准备插入的位置例如此处我们插入在了IEND数据块之前(00 00 00 49……)直接键入16进制的payload即可
保存后依然不会影响PNG文件的浏览。
第十三步,下面我们通过C语言脚本自动去掉PNG文件所有的辅助模块后,写入Payload数据块tEXt,并将该程序保存为AddPayload.cpp,以下为完整的代码
将文件new_bak.png改名为new.png覆盖原文件并执行编译后的代码
接下来我们需要将该文件上传到网盘或Web服务器上。实验中的Web服务器的根路径为C:\Program Files (x86)\upload-labs\WWW。
第十四步,编写powershell脚本代码以利用图片中payload,具体代码如下:url地址根据实际环境修改,如本例的win10实验机IP为172.16.1.100
为了演示实验效果,直接在本机上使用快捷键Win+R打开命令运行功能,然后输入命令powershell,打开powershell命令行
输入如下的指令:
逐行解释一下:
运行后触发如下所示的程序
这里给出的方法仅供演示,更多方法待大家自己去挖掘。
实验结束,关闭虚拟机。