隐写术
-
隐写术(Steganography,简写Stega)
- 一门关于信息隐藏的技巧与科学
- 信息隐藏:不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容
- 与密码学(Cryptography)不同。密码学更加关注对信息的加密和解密算法,隐写术更注重对信息和行为的隐藏
-
隐写题目的类型
- 图片隐写
- 图片EXIF信息隐写
- 图片高度缩减隐写
- 图片LSB地位隐写
- 文档隐写
- 文本隐写
- 压缩包隐写
- 其他文档格式(eg. word/pdf/html文件)
- 音频、视频隐写
- 其他形式隐写
- 图片隐写
图片隐写
- 常用解题工具
- Strings:文本隐写分析工具
- Binwalk/dd/foremost:图片分离工具
- Winhex/ultraeditor:文件16进制编辑器
- Stegsolve.jar:图层分析工具
EXIF信息隐写
-
EXIF(Exchangeable image file format)
- 可交换图像文件格式
-
支持的图片格式:JPEG、TIFF、XMP等等
-
查看工具
- 类Unix系统:exiftool
- windows系统:图片-属性查看
-
与CTF的结合,将Flag或者密文 写入属性中
左图直接将Flag放在备注
右图将Flag的Base64密文放在版权,解密后可以得到Flag
LSB隐写
- LSB(Least Significant Bit),最低有效位
- 图片像素一般是由RGB三原色组成,每一个颜色占用8位,0x00~0xFF,也就是256种值,一像素点共包含了256^3种颜色
- 人的肉眼能区分的只有其中一小部分
- 修改RGB颜色分量中最低的二进制位,人眼无法区分
——例如:将字符’A’隐藏进图片LSB,即把’A’的二进制ASCII码”01100001“写到LSB通道的最低位
解题思路:
- 图片分析——确认是不是LSB隐写
- 图层分离——查看LSB
工具:
- 可视化图层分析工具:Stegsolve.jar
- 对于比较难的题,需要自己编写python脚本,PIL.Image库
- 工具Stegsolve
- 主要功能:analyse
- File format:文件格式,查看图片的具体信息
- Data Extract:数据抽取,抽取图片中隐藏数据
- Frame Browser:帧浏览器,对GIF动图进行分离
- Image Combiner:图片融合
例题一
简单的查看每个图层即可获得flag
例题二
需要对Alpha图层和Green图层进行异或计算,需要将两个图层进行融合
- 找到Alpha图层,进行另存
- 找到Green图层,进行另存
- 打开其中一个图层,选择Analyse->Image Combiner进行融合
例题三
迅速浏览三个图层,可以发现Red/Green/Blue图层的最低位有异常信息
需要将三个图层的最低有效位进行融合,这里需要用到Python自己编写脚本
from PIL import Image
im=Image.open("../stega_image_lsb/LSB.bmp")
pix=im.load()
width,height=im.size
extracted_bits=[] # [0,1,0,0,0,0,1,0,0,1]
for y in range(height):
for x in range(width):
r,g,b=pix[(x,y)]
extracted_bits.append(r & 1) # 计算最低有效位
extracted_bits.append(g & 1)
extracted_bits.append(b & 1)
extracted_byte_bits=[extracted_bits[i:i+8] for i in range(0,len(extracted_bits))]
with open("../stega_img_lsb/LSB2.bmp","wb") as out:
for byte_bits in extracted_byte_bits:
byte_str=''.join(str(x) for x in byte_bits) #01000010
byte=chr(int(byte_str,2)) # ascii
out.write(byte)
得到输出的图片,就可以发现隐藏的flag
高度缩减隐写
png图片格式
- PNG signature无法进行修改,修改后,计算机无法识别PNG图片
- 其他三个数据块可以修改
- LSB隐写的本质是修改了IDAT 图像数据块的数据,IDAT可以存在多个数据块,因此我们写入多一个数据块也不会对肉眼可观测的图片造成影响
- 遇到IEND之后,后面的数据统统被抛弃,因此后面增加的数据是不会影响显示的
-
PNG图片基本数据单元
- PNG图片以数据块(chunk)为数据单元存储在计算机中
- 每个数据块包含以下四个部分
- 因为存在CRC的检测,因此我们需要知道先验的结构,知道哪些数据部分能改,哪些不能改
-
IHDR数据块
例题
- 通过修改PNG图片的高度值,来对部分信息进行隐藏
- 解题思路:
- 分析题目提示
- 查看图片内容
- 计算校验和(熟悉图片格式、crc校验、进制转换)
通过放入图片,查看png的二进制内容
我们将IHDR的数据部分放入CRC在线计算,可以发现检验码对不上,因此我们可以知道IHDR部分有数据篡改
我们通过将高度尝试调整成宽度一致,可以获得校验码
因此我们可以知道,该图片进行了高度缩减,然后修改高度,即可得到原图
结尾隐写
-
PNG图片结尾隐写
- 在IEND数据块(49 45 4E 44 AE 42 60 82)之后附加额外数据内容,该数据不会被图片查看器加载、解析,从而达到隐藏信息的目的
-
解题工具
- windows平台:Winhex、UltraEditor
- Kali环境:binwalk、dd、foremost指令
-
任何文件,都可以在文件尾附加隐写信息
-
Winhex实用技巧
- 查找文本:Ctrl+F
- 查找16进制:Alt+Ctrl+F
- 搜索下一个:F3
- 快速选择大数据块:
- 上下左右方向键移动光标
- alt+1选定要修改的数据块的起始字节
- 再使用alt+2选定结束字节
- 保存数据块到新文件
- 右键-edit-copy block-into new file
通过搜索PNG签名,我们可以知道这里其实有两张PNG的内容,因此我们可以进行图片的分离
在kali系统,我们可以使用binwalk对图片进行分析
可以发现有两张PNG image,然后我们可以使用dd指令分离两张图片
- 在文件的结尾标志符之后附加隐藏信息,而不破坏源文件
- 文本信息
- 其他文档
- 一般,隐写内容都是附加在源文件的结尾
- 如果附加在头部,破坏了文件头,可能导致文件无法识别
- 如果附加在中间,有可能破坏了源文件的信息
文档结尾隐写
-
解题工具
- strings命令:查找可打印字符串
- binwalk命令:分析文件隐写内容
- dd、foremost命令:分离文件
-
流程
- binwalk [filename] # 也可以添加"-e"参数直接分离 - foremost [filename] # 生成一个output的文件夹 - dd if=源文件.jpg of=目标文件.jpg skip=偏移量 bs=1
-
strings 命令
- 在对象文件或二进制文件中查找可打印的字符串
-a --all:扫描整个文件,而不是只扫描目标文件初始化和装载段 -f --print-file-name:在显示字符串前先显示文件名 -t --radix={o,d,x}:输出字符的位置,基于八进制,十进制或者十六进制 -e --encoding={s,S,b,l,B,L}:选择字符大小和排列顺序——s:7-bit,S=8-bit,{b,l}=16-bit,{B,L}=32-bit
- 我们使用strings+[filename]命令即可
在线工具
练习平台
音频隐写
- 和图片一样,数字音频也可以用于信息隐写
- 音频载体信号存在冗余,为隐蔽信息提供支持
- 人类听觉系统频谱范围是20Hz18kHz,但2kHz4kHz信息最为敏感
- 人类听觉系统只对相对相位敏感,而无法感知绝对相位
- 解题工具
- Audacity:开源音频处理软件,分析音频的频谱、波形
- MP3Stego:音频数据分析与隐写工具
摩尔斯电码
- 摩尔斯电码(Morse code),又称莫斯密码
- 一种时通时断的信号代码
- 发明于1837年,广泛应用于二战时期的电报加密
- 通过不同的排列顺序来表达不同的英文字母、数字和标点符号
- 基本信号
- “.” 短促的点信号 “滴”
- “-” 保持一定时间的长信号 “嗒”
- 组成信号
- 滴=1t/嗒=3t/滴答间隔=1t/字符间隔=3t/单词间隔=7t
例题一
实验吧——“奇妙的音乐”
题目链接:http://ctf5.shiyanbar.com/crypto/123.zip
解压后我们得到一个压缩包和一张图片
通过解决图片上的盲文,可以得到“KMDONOWG”
然后我们点开压缩包,发现解压需要密码,然后我们将上述提到的内容作为密码输入
能够解压出一个音频文件
我们打开音频文件,里面就是一段电报声,我们可以很容易得到是一个摩尔斯电报
然后我们放入Audacity里面获得频谱,最后进行解码,得到最后的flag
波形隐写
——题目来源ISCC2017 普通的disco
在攻防世界里可以得到原题攻防世界 (xctf.org.cn)
通过播放,我们可以发现音频的开头存在噪声,而且开头存在一段空白,因此可以推测,开头经过了处理
然后我们使用Audacity不断放大前面的开头
——通过波形只有-1~1之间跳变,我们可以知道它的波形是一段二进制串(好难QAQ)
然后我们将这段二进制使用ASCII解码即可得到flag
string = '110011011011001100001110011111110111010111011000010101110101010110011011101011101110110111011110011111101'
flag = ''
for i in range(0, len(string), 7):
bin_str = string[i: i + 7]
flag += chr(int(bin_str, 2))
print(flag)
音频频谱隐写
-
直接将flag信息隐写到音频的频谱里面
-
这类题比较简单,直接放进工具音频分析即可
MP3编码隐写
- 将数据隐藏在MP3文件的奇偶校验块中
- MP3stego
- MP3编码隐写与还原工具
- 数据隐写: encode -E hidden_text.txt -P pass svega.wav svega_stego.mp3
- 数据还原:decode -X -P pass svega_stego.mp3
例题
- ISCC2016:Music Never Sleep
运行后,提示需要密码
因此,我们又需要去找密码,这里就可以使用之前提到的winhex工具
搜索到密码之后,就可以继续工作
将decode的内容放进了一个文档中,打开后可以得到一个base64的密文,然后将密文进行解码即可得到flag