谨以此题来对PNG
隐写进行学习,题目来自CTFshow
,文中提到的工具下载地址已附在文后。
题目描述:
想要我的flag吗?如果想要的话,那就去找吧,我把全部的flag都放在那里。
下载地址https://ctfshow.lanzoui.com/iDEiVmr8m4d
本场比赛共有18题,但只有1个附件文件(见第1题),所有flag均可以从附件中获取;
1、所有的flag开头和结尾均为#,中间由字母、数字或下划线组成;
2、本场比赛不使用任何可以设置密码的隐写方法,包括可以将密码留空的隐写方法;
3、原理类似的隐写方法在确保不互相干扰的前提下可能会以多种方式使用;
4、如果从附件提取的隐写信息为字符串形式,可能需要转码得到指定格式的结果;
5、如果从附件提取的隐写信息为另一张图片,该图片不会再包含隐写信息,即不存在套娃隐写;
6、所使用的字体均为微软雅黑,若有字符无法分辨,请与字体对比查看;
7、取得类似#abcd_1234#的字符串后,请计算其MD5值(包含头尾的#号);
8、每道题目都给出了一段MD5值,请找到MD5值匹配的题目后,将flag包上ctfshow{}格式提交。
0x00 直接获取
One PieNG 1、One PieNG 2
One PieNG 1
的flag
在文件名。One PieNG 2
的flag
在图片上。
One PieNG 1
:ctfshow{#St4rt_fr0m_th1s_5tr1ng#}
One PieNG 2
:ctfshow{#Th1s_i5_s0_34sy!!!#}
0x01 十六进制 && EXIF
010 Editor
是一款功能强大的代码编辑器,使用可帮助用户轻松编辑任何文件、驱动器或进程的文本和十六进制代码。旨在快速轻松地编辑计算机上任何文件的内容。该软件可以编辑文本文件,包括Unicode
文件,批处理文件,C / C ++
,XML
等,在CTF
中常用于查看文件的十六进制代码。
在使用010 Editor
查看PNG
格式图片时可以借助他的PNG.bt
模板,能够让我们快速找到图片的每一个段的地址,方便查找。
One PieNG 10
这里我们将图片拖入010 Editor
开头找到One PieNG 10
的flag
。开头的tEXt
表示这个位置是PNG
图像的tEXt
块,它是一种文本块,用于存储关于图像的附加文本信息。这些信息不影响图像的显示,但可以用于提供有关图像内容、作者、版权等的描述性文本。
One PieNG 10
:ctfshow{#A_k3y_1n_exif#}
One PieNG 17
PNG
类型的题常在文件最后藏一些东西,我们拖到最后,在文件的最后一个chunk
找到One PieNG 17
的flag
。
One PieNG 17
:ctfshow{#HexEditor_wi11_b3_he1pfu1#}
One PieNG 13
第三个flag
,也是一个tEXt
块,One PieNG 13
的flag
。
One PieNG 13
:ctfshow{#Ju5t_a_1one1y_tEXt_chunk#}
One PieNG 11
开头处还有一串字符串,b58
开头,应该是base58
编码。这段数据被<photoshop:City >
标签包裹,表示它是PNG
图片的EXIF
数据。
PNG
图像格式通常不包含EXIF(Exchangeable Image File Format)
数据,EXIF
数据通常用于JPEG
格式文件。EXIF
数据主要用于存储照片的元数据,如拍摄日期、相机型号、曝光时间等,可用exiftool
查看。然而,PNG
格式的图像通常使用其他方式来存储元数据,例如tEXt
头块或zTXt
头块。
可以用CyberChef
解码得到One PieNG 11
的flag
。
One PieNG 11
:ctfshow{#An0th3r_key_1n_3xif#}
One PieNG 12
在这串base58
字符串上面还有一串十六进制编码字符串。
解码一下就是One PieNG 12
的flag
。
One PieNG 12
:ctfshow{#A_key_fr0m_Ph0t0sh0p#}
exiftool
在上面提到了exif
,那我们可以尝试用exiftool
去查看。
ExifTool
是一款功能强大的命令行工具,用于读取、编辑和写入各种图像、音频和视频文件的元数据。它可以识别并处理各种不同格式的文件,包括照片、音频文件、视频文件等,从而让您能够查看和修改这些文件中包含的元数据信息。
可以看到,通过查看EXIF
信息能够直接得到三个flag
。
0x02 LSB
LSB
LSB(Least Significant Bit)
隐写是一种基于图像的隐写技术,它将秘密信息嵌入到图像的最低有效位(最不重要的位)中,从而在视觉上几乎不影响图像的外观。LSB
隐写是一种简单但常用的隐写方法,适用于各种图像格式,如 BMP
、PNG
、JPEG
等。
LSB
隐写的基本原理是将要隐藏的数据的二进制位逐一嵌入到图像像素的最低有效位中,这样修改后的像素值在视觉上几乎不会引起明显的变化。在提取隐写信息时,只需读取图像中最低有效位的数据,即可还原出隐藏的数据。
一个像素点的数据一般是(r,g,b,a)
这样,a
通道不一定存在,也就是只有RGB
,每个通道的数值都是0-255
也就是2^8
个,所以刚好能有一个字节表示,一般来说会把数据隐藏在0-3
这几个低位上面,如果大于3
了色差就会比较明显。
举个例子,我们使用如下python
代码就实现了一个LSB
,将数据隐藏到了R, G, B
三个颜色通道的最低位,并进行数据还原。
from PIL import Image
# 将字符转换为8位二进制
def char_to_binary(char):
return format(ord(char), '08b')
# 将字符串转换为二进制
def string_to_binary(message):
binary_message = ''.join(char_to_binary(char) for char in message)
return binary_message
# 将二进制信息嵌入图像的 LSB 中
def embed_message(image_path, binary_message):
pic = Image.open(image_path)
w, h = pic.size[0], pic.size[1]
binary_index = 0
for i in range(w):
for j in range(h):
# 获取图像中的像素值
pixel = list(pic.getpixel((i, j)))
for color_index in range(3):
if binary_index < len(binary_message):
# 清除像素值的最低位,然后将消息的二进制位嵌入其中
pixel[color_index] &= 0xFE
pixel[color_index] |= int(binary_message[binary_index])
binary_index += 1
# 更新图像像素值
pic.putpixel((i, j), tuple(pixel))
# 保存嵌入了信息的新图像
pic.save("stego_image.png")
print("Message embedded successfully!")
# 从图像中提取并还原二进制信息
def extract_message(image_path):
pic = Image.open(image_path)
w, h = pic.size[0], pic.size[1]
binary_message = ""
for i in range(w):
for j in range(h):
# 获取图像中的像素值
pixel = pic.getpixel((i, j))
for color_index in range(3):
# 提取像素值的最低位,并添加到二进制消息中
binary_digit = pixel[color_index] & 1
binary_message += str(binary_digit)
return binary_message
# 嵌入信息
message_to_embed = "Hello, this is a hidden message!"
binary_message_to_embed = string_to_binary(message_to_embed)
embed_message("original_image.png", binary_message_to_embed)
# 提取并还原信息
restored_binary_message = extract_message("stego_image.png")
restored_message = ''.join(
chr(int(restored_binary_message[i:i + 8], 2)) if chr(int(restored_binary_message[i:i + 8], 2)).isprintable()else "" for i in range(0, len(restored_binary_message), 8))
print("Restored Message:", restored_message)
在这个代码中,遍历图片的像素点,然后对每一个像素点的R, G, B
三个颜色通道进行操作,依次将最低位清零,这是为了将最低位的空间腾出来,用于隐藏消息的二进制位。然后通过按位或操作将消息的二进制位与像素的最低位进行合并。
实现了将消息的每个二进制位逐一嵌入到图像的 RGB
通道的最低有效位中。这样做不会明显改变图像的外观,但可以在最低位上存储隐藏的二进制消息。
而数据的还原,也是遍历像素点,然后对每一个像素点的R, G, B
三个颜色通道的最低位数据依次保存,最后转化为字符串。
StegSolve
StegSolve
是一个用于隐写分析和图像处理的工具。它专门用于检测和分析在图像中隐藏的信息,如隐写术、隐写图像、隐写文本等。StegSolve
提供了各种功能,可以帮助用户发现和分析隐藏在图像中的信息。
StegSolve
工具通常用于计算机安全领域,特别是隐写分析和数字取证。使用 StegSolve
,用户可以检测和分析隐藏在图像中的信息,从而揭示潜在的威胁或者隐藏的数据。
StegSolve
的界面如下所示,可以通过最下方的箭头来切换通道。
当我们发现存在数据修改的通道时,可以通过上方的Analyse > Data Extract
来导出数据,如下方所示。
左边的Bit Planes
表示导出数据的通道及其位数,通过查看图片通道存在数据修改的地方来进行选择。
右上方的Extract By
的Row
和Column
两个选项表示按照行或列的顺序访问数据,我们可以通过查看通道时数据是横向还是纵向来对该选项进行选择。
MSB First
和LSB First
两个选项作用为设置取通道数据的先后顺序,读取数据时,每次仅读取1Bit
,该项是控制读取一个通道字节数时,读取的方向,MSBFirst
表示从高位读取到低位,LSBFirst
表示从低位读取到高位。因此只有当通道勾选的Bit
个数大于1时,该选项才会影响返回的结果。该选项只能通过多次尝试来进行判断。
而Bit Plane Order
选项则是通道顺序,一个像素值包含多个通道,不同通道的读取数据,Alpha一直是最先读的,然后会根据该项的配置决定读取顺序。该选项只能通过多次尝试来进行判断。
比如,有个像素数据是(1,2,3)
,二进制表示就是0000 0001, 0000 0010, 0000 0011
,我们只勾选0
位顺序选RGB
那么取数据的时候就会依照r,g,b
的顺序 取0
通道的数据,也就是1 0 1
,然后再把这个二进制数据转成字节,就恢复数据了。
如果我们选择的是MSB
,并且同时选择了0
和1
位,那么读取的就是01 10 11
,先读取1
位再读取0
位。反之选择的是LSB
的话,读取的就是10 01 11
,先读取0
位再读取1
位。
One PieNG 8
拖入StegSolve
中,在Alpha、Red、Green、Blue
四个通道的7位都发现了左边明显的小黑点,说明这个位置大概率被修改过,然后查找其他同样有修改痕迹的通道,通过通道的排列组合导出数据。
勾选四个通道,选择Column
模式和GBR
,也就是按照行访问数据,设置取通道数据的先后顺序为GBR
,提取出flag
。
One PieNG 8
:ctfshow{#zsteg_do35_no7_a1w4ys_w0rk#}
One PieNG 5
Blue
通道的0位也存在一个flag
。
One PieNG 5
:ctfshow{#You_st3gs0lved_me!!!#}
One PieNG 6
在RGB
通道的0位上边都有黑点。
选择RGB
通道的0位。
One PieNG 6
:ctfshow{#LSB_1s_v3ry_e4sy_righ7?#}
One PieNG 7
在Red
和Green
通道的0位左边竖着的位置有黑点,但是Blue
通道的0位没有。
选择RG
通道的0位,选择列。
One PieNG 7
:ctfshow{#5omet1mes_LSB_g0es_co1omn_f1r5t#}
One PieNG 9
可以看到在Red
通道的2、1位在上方的黑点要比0位的长,Blue
和Green
通道也同理。
选择RG
通道的1、2位,选择LSB First
,就可以看到PK
字符,显然是压缩包的头文件,导出。
因为导出数据会导出一些冗余的数据,我们得将其删除,或者winrar
修复一下才能解压,得到flag
。
One PieNG 9
:ctfshow{#Wh4t_1s_6it_0rder_4nd_y0u_c4n_LSB_b1nd4ta_to0#}
0x03 提取隐藏文件
binwalk
是一个用于分析二进制文件的工具,它主要用于提取和识别嵌入在文件中的其他文件、元数据和隐藏信息。它被广泛用于数字取证、嵌入式设备的分析、安全审计等领域。
Foremost
是一个开源的数字取证工具,用于从存储设备(如硬盘、内存卡、镜像文件等)中恢复丢失的文件。它专门用于恢复已删除、损坏或隐藏的文件,特别是图像、音频、视频和文档文件等。Foremost
在数字取证、数据恢复、安全研究和计算机取证等领域广泛使用。
One PieNG 18
之前在010 Editor
中发现下面还有个PNG
头,用binwalk
来看一下。确实存在一个PNG
文件。
foremost #St4rt_fr0m_th1s_5tr1ng#.png
成功提取。
One PieNG 18
:ctfshow{#He110_I_4m_Tw0_PieNG#}
0x04 修改高度
One PieNG 3、One PieNG 4
通过010 Editor
直接修改PNG
文件的高度,得到两个flag
。
One PieNG 3
:ctfshow{#Pn9_He1gh7_6e_ch4ng3d#}
One PieNG 4
:ctfshow{#M4yb3_we_sh0uld_9o_d33per#}
一般修改高度获取flag
的题都是通过爆破CRC
获取图片高度,但是这里CRC
被修改过了,正常爆破CRC
获取图片高度的话只能拿到上面一个flag
,而下面一个需要自己修改高度为很大的一个值才能看到。
0x05 IDAT
IDAT
在 PNG
图像中,IDAT(Image Data)
块是用于存储图像的实际像素数据的部分。而 zlib
则是一种压缩库,常用于对 IDAT
块中的图像数据进行无损压缩。
以下是关于 IDAT 和 zlib 的更详细说明:
1.IDAT 块(Image Data Block):IDAT
块是 PNG
图像中最重要的部分之一,它包含了图像的实际像素数据。PNG
图像可以有多个 IDAT
块,每个块包含图像的一部分数据。这种分块的设计可以使得 PNG
图像能够支持渐进式加载和更好的压缩。IDAT
块中的数据是经过滤波和压缩处理后的,它们组合在一起形成最终的图像数据。2.zlib 压缩:zlib
是一个通用的数据压缩库,它支持 DEFLATE
压缩算法。在 PNG
图像中,IDAT
块的数据会首先经过滤波器处理,然后再使用 zlib
进行无损压缩。DEFLATE
压缩算法是一种使用 LZ77
算法和哈夫曼编码的压缩方法,可以有效地减小图像数据的大小。这样,使用 zlib
压缩后的 IDAT
块将占用更少的存储空间,同时保持图像数据的完整性。
总结起来,PNG
图像中的 IDAT
块存储了图像的像素数据,而 zlib
则是用于对 IDAT
块中的图像数据进行无损压缩的库。这两者的结合使得 PNG
图像既能够高效地存储图像数据,又能够保持图像的质量和完整性。
One PieNG 15
使用binwalk
提取zlib
数据。
One PieNG 15
:ctfshow{#IDAT_i5_a_alib_p4cka9e#}
或者在010 Editor
中找到这个长度不正常的IDAT
块,前一块IDAT
长度还没有达到最大,显然多出来的这块长度很短的IDAT
是有问题的。
用python
脚本进行解密。
import zlib
import binascii
IDAT_hex = b"789C53F674710C89CF348D4F8CAF32CC4C8A2F3049CE4EB44C5506005F0E07CB"
IDAT_bytes = binascii.unhexlify(IDAT_hex)
decompressed_data = zlib.decompress(IDAT_bytes)
result = binascii.hexlify(decompressed_data)
print(decompressed_data)
One PieNG 14
PNGDebugger
是一个用于分析和调试 PNG
图像文件的工具。它专门用于查看 PNG
图像的内部结构、图像通道、像素值和元数据等信息,以帮助用户了解和解决 PNG
图像相关的问题。
TweakPNG
是一个用于编辑和分析 PNG
图像文件的工具。它允许用户查看和修改 PNG
图像的各个部分,包括图像块、元数据和颜色通道等。TweakPNG
可以用于检查 PNG
图像的有效性、优化图像、编辑元数据等。
用PNGDebugger.exe
跑一下,发现前面几个IDAT
的CRC
都报错了,但是后面的IDAT
的CRC
没有报错。
用TweakPNG
打开图片,删掉九个报错的IDAT
块。
保存,得到新的图片。
One PieNG 14
:ctfshow{#eXtr4_IDAT_of_an0th3r_Pn9#}
为什么把这九个IDAT
删了就能得到一张新的图片呢?
因为类型为 IDAT
的数据块用来存放图像数据,跟其他关键数据块不同的是,其数量可以是连续的复数个,png
获得图片像素本质是确定png
头IHDR
获得宽高和位深 然后就去IDAT
块里面提取所有数据,在这个地方,就是把两张图片的IDAT
拼在了一块,前九个IDAT
的数据就是我们开始看到的图片的数据,而剩下的IDAT
就是上图所示的图片的数据。
One PieNG 16
最后这个有点坑,几个报错的IDAT
块的crc-code
开头都是0x00
,这些数字都在常见字符的ASCII
码范围内。将几个报错的CRC
都拼起来,得到23483164655F683378643437615F316E5F6368756E6B5F43524323
。
十六进制解码得到flag
。
One PieNG 16
:ctfshow{#H1de_h3xd47a_1n_chunk_CRC#}
0x06 提到的工具
010 Editor
:https://www.sweetscape.com/download/010editor/
CyberChef
:https://github.com/gchq/CyberChef
exiftool
:https://exiftool.org/
StegSolve
:http://www.caesum.com/handbook/Stegsolve.jar
binwalk
:https://github.com/ReFirmLabs/binwalk/releases
foremost
:http://foremost.sourceforge.net/#DOWNLOAD
PNGDebugger
:https://github.com/rvong/png-debugger
TweakPNG
:http://entropymine.com/jason/tweakpng/#download
0x07 免责声明
本文仅限于技术研究学习,切勿将文中技术细节用作非法用途,如有违者后果自负。
关于我们
“TERRA星环”安全团队正式成立于2020年,是贵州泰若数字科技有限公司旗下以互联网攻防技术研究为目标的安全团队。团队核心成员长期从事渗透测试、代码审计、应急响应等安服工作,多次参与国家、省级攻防演练行动,具备丰富的安服及攻防对抗经验。
团队专注于漏洞挖掘、漏洞研究、红蓝对抗、CTF夺旗、溯源取证、威胁情报、代码审计、逆向分析等研究。对外提供安全评估、安全培训、安全咨询、安全集成、应急响应等服务。
原文始发于微信公众号(TERRA星环安全团队):CTF | PNG隐写入门赛 一张图片十八个flag
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论