# MISC—Picture
一键梭哈网站:https://aperisolve.fr/
# 盲水印隐写
一张图片的情况
可以使用 隐形水印工具 V1.2 或者 WaterMark 来提取水印
两张图片的情况
1 2 3 先把要处理的图片拉入BlindWaterMark-master文件夹,然后使用如下命令 py bwmforpy3.py decode day1.png day2.png flag.png --oldseed Tips:这里还会出现FFT(傅里叶盲水印):直接运行CTFD中的FFT.py
# 图片的分离和拼接
(1) 可以用 kali 的 convert 分离和 montage 拼接命令
1 2 3 4 5 6 分解GIF的命令:convert glance.gif flag.png 水平镜像翻转图片:convert -flop reverse.jpg reversed.jpg 垂直镜像翻转图片:convert -flip reverse.jpg reversed.jpg 合成图片的命令:montage flag*.png -tile x1 -geometry +0+0 flag.png -tile是拼接时每行和每列的图片数,这里用x1,就是只一行 -geometry是首选每个图和边框尺寸,我们边框为0,图照原始尺寸即可
(2) 使用在线网站分解:https://tu.sioe.cn/gj/fenjie/,stegsolve 也可以
(3) 用 py 脚本跑
1 2 3 4 5 6 7 8 9 10 import osfrom PIL import Imageim = Image.new('RGB' , (2 *201 , 600 )) PATH = 'E:/ctf/glance.gif' FILE_NAME = [i for i in os.listdir(PATH)] width = 0 for i in FILE_NAME: im.paste(Image.open (PATH+i), (width, 0 , width+2 , 600 )) width += 2 im.show()
# 像素点合成
注:Linux wc 命令用于计算字数。
-l 或–lines 显示行数。
-w 或–words 只显示字数。
-c 或–bytes 或–chars 只显示 Bytes 数。
可以改个标题后用在线网站将 txt 转换为 ppm 文件 https://convertfree.com/cn/txt-to-ppm#google_vignette
# OurSecret 隐写
拉入 OurSecret,输入密码解密,得到隐藏文件
# 拼图题
碎图片合成一张图片
1 2 3 #在Windows中使用imagemagick处理 magick.exe montage *.png -tile 18 x10 -geometry 125 x125+0 +0 flag.jpg magick montage *.png -tile 40 x22 -geometry +0 +0 flag-0 .png
1 2 3 4 5 6 7 拉入kali里处理,如果是碎的图片, 先使用 montage *.PNG -tile 12x12 -geometry +0+0 out.png合成一张图片 *.png表示匹配所有图片 -tile表示图片的张数 -geometry +0+0表示每张图片的间距为0 合成后要先查看图片的宽高(宽高要相等,不相等要用PS调整)
也可以使用 gaps 智能拼图
1 2 3 4 5 6 7 8 gaps --image=out.png --generation=30 --population=144 --size=30 --save --image 指向拼图的路径 --size 拼图块的像素尺寸 --generations 遗传算法的代的数量 --population 个体数量 --verbose 每一代训练结束后展示最佳结果 --save 将拼图还原为图像
1 2 3 4 5 6 gaps --image=flag.jpg --generations=50 --population=180 --size=125 --verbose -generations 你要迭代多少次 -population 你有多少个小拼图 --size 每张小图,也就是拼图小块的大小 --verbose 实时显示
# 近邻法缩放图片
在 PS 中打开图片,然后在更改图像大小中,将宽高调成指定像素并将重新采样选项选为邻近(硬边缘)
# pixeljihad(有密码)
直接使用在线网站解密即可:PixelJihad (sekao.net)
# 隐写文本可能藏在原图片和隐写文件的中间
直接在 010 中搜索 IEND,然后查看后面有没有额外内容即可
# 提取图片中等距的像素点得到隐写的图片
在 windows 的终端 wt 中运行 CTFD 中的 Get_Pixels.py
# silenteye 隐写
特征:放大图像后会有行列不对齐的小灰块
直接用 silenteye 打开输入密钥 decode 即可,默认密钥是 silenteye
# 图片报错改宽高后图片无变化
可以再 foremost 一下
# DeEgger Embedder 隐写
可以直接使用 DeEgger Embedder 工具 extract files
# flag 可能藏在 exif 中
直接在 linux 中输入以下命令查看即可,如果偷懒也可以直接使用 破空 flag 查找工具 进行查找
# 给了两张图片,flag 藏在每行不同像素的个数中
例题 1-2023 羊城杯初赛 - 两支老虎
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from PIL import Image, ImageChopsimg1 = Image.open ("1.png" ) width1,heigth1 = img1.size img2 = Image.open ("2.png" ) width2,heigth2 = img2.size img2 = img2.crop((0 ,0 ,1134 ,720 )) width2,heigth2 = img2.size diff_dit = {} diff = ImageChops.difference(img1,img2) width3,heigth3 = diff.size for x in range (width3): for y in range (heigth3): pixel3 = str (diff.getpixel((x,y))) if pixel3 not in diff_dit: diff_dit[pixel3] = 0 else : diff_dit[pixel3] += 1 print (diff_dit) for y in range (heigth1): cnt = 0 for x in range (width1): pixel1 = img1.getpixel((x,y)) pixel2 = img2.getpixel((x,y)) if pixel1 != pixel2: cnt += 1 if cnt != 0 : print (chr (cnt),end='' )
# PNG
# CRC 错误 (不能乱改),改宽高
脚本爆破
# LSB (最低有效位) 隐写:
没有密钥的情况
1 2 3 4 zsteg -a (文件名) -b的位数是从1开始的 zsteg zlib.bmp -b 1 -o xy -v 提取文件并导出 zsteg -e b1,r,lsb,xy 3.png > 123.jpg
stegsolve 保险一点
有密钥的情况(cloacked-pixel)
lsb 隐写的可能是加密后的数据,i 春秋最喜欢的 cloacked-pixel
拉到 kali/WSL 里用 cloacked-pixel 命令解密出数据
1 python2 cloacked-pixel-master/lsb.py extract 0.png out.data f78dcd383f1b574b
0.png 是隐写后的图片;out.data 是隐写内容保存的位置;f78dcd383f1b574b 是密钥
# IDAT 块隐写
(1) 解压 zlib 获得原始数据
然后用 010 提取数据扔进 zlib 脚本解压获得原始数据
将异常的 IDAT 数据块斩头去尾之后使用脚本解压,在 python2 代码如下:
1 2 3 4 5 6 import zlibimport binasciiIDAT = "789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667" .decode('hex' ) result = binascii.hexlify(zlib.decompress(IDAT)) print (result.decode('hex' ))print (len (result.decode('hex' )))
(2) 加上文件头爆破宽高得到新的图片
一般出问题的 IDAT Chunk 大小都是比正常的小的,很可能在图片末尾
如果不确定是哪一个有问题,可以尝试都提取出来,一个一个分析
可以使用 tweakpng 辅助分析,但是一般用 010 的模板提取分析就够了
我们可用 kali 中的 ** pngcheck -v 0.png
** 检查 IDAT
# png 数据末尾藏 zip
补上压缩包的文件头,然后提取出来,解压 (可用 stegpy 得到解压密码)。
或者直接 foremost 提取
# apngdis_gui
一张 png 图片还可能是 apng,直接用 apngdis_gui 跑一下,可以分出两张相似的 png
# CVE-2023-28303 截图工具漏洞
可以使用 Github 上大佬写好的工具一把梭,前提是需要知道原图的分辨
# JPG
# 用 stegdectet 看看是什么加密:
.\stegdetect.exe -t jopi -s 10.0 .\0.jpg
# steghide 隐写
1 2 steghide extract -sf filename -p passwd
1 2 3 4 5 6 7 8 9 10 11 12 可以用下面这个脚本爆破 for line in `cat $2 `;do steghide extract -sf $1 -p $line > /dev/null 2>&1 if [[ $? -eq 0 ]];then echo 'password is: ' $line exit fi done
1 2 stegseek filename rockyou.txt
# outguess 隐写
1 2 3 outguess -k "abc" -r mmm.jpg flag.txt
# F5-steganography-master
1 2 3 4 5 #有密码的情况 java Extract beautiful.jpg -p passwd #无密码的情况 java Extract beautiful.jpg #解密出来的数据会放到F5文件夹下的output.txt中
# JPG 宽高隐写
010 打开 JPG 图片,找到 struct SOF 块数据,手动调整宽高即可
# BMP
# bmp 宽高爆破
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 import osimport timeimport mathimport argparseparser = argparse.ArgumentParser() parser.add_argument("-f" , type =str , default=None , required=True , help ="输入同级目录下图片的名称" ) args = parser.parse_args() SAVE_DIR = os.getcwd() def save_img (data, width=None , height=None , sqrt_num=None ): with open (os.path.join(SAVE_DIR, "fix_width.bmp" ), "wb" ) as f: f.write(data[:0x12 ] + width.to_bytes(4 , byteorder="little" , signed=False ) + data[0x16 :]) with open (os.path.join(SAVE_DIR, "fix_height.bmp" ), "wb" ) as f: f.write(data[:0x16 ] + height.to_bytes(4 , byteorder="little" , signed=False ) + data[0x1a :]) with open (os.path.join(SAVE_DIR, "fix_sqrt.bmp" ), "wb" ) as f: f.write(data[:0x12 ] + sqrt_num.to_bytes(4 , byteorder="little" , signed=False ) * 2 + data[0x1a :]) def get_pixels_size (data ): bfSize = int .from_bytes(data[0x2 :0x2 +4 ], byteorder="little" , signed=False ) bfOffBits = int .from_bytes( data[0xa :0xa +4 ], byteorder="little" , signed=False ) biBitCount = int .from_bytes( data[0x1c :0x1c +2 ], byteorder="little" , signed=False ) channel = biBitCount // 8 return (bfSize - bfOffBits) // channel if __name__ == '__main__' : file_path = os.path.abspath(args.f) if os.path.splitext(args.f)[-1 ] != ".bmp" : print ("您的文件后缀名不为BMP!" ) time.sleep(1 ) exit(-1 ) with open (file_path, "rb" ) as f: data = f.read() col = abs (int .from_bytes(data[0x12 :0x12 +4 ], byteorder="little" , signed=True )) row = abs (int .from_bytes(data[0x16 :0x16 +4 ], byteorder="little" , signed=True )) pixels_size = get_pixels_size(data) width, height = pixels_size // row, pixels_size // col sqrt_num = int (math.sqrt((pixels_size))) save_img(data, width=width, height=height, sqrt_num=sqrt_num) print ("温馨提示:由于填充字节的问题,所以可能会偏差几个像素!" ) print (f"1.修复宽度: {width} " ) print (f"2.修复高度: {height} " ) print (f"3.修复宽度高度为: {sqrt_num} " ) time.sleep(1 )
# wbStego4open 隐写
用 wbStego4open 直接 decode
# silenteye 隐写
直接拉入 silenteye 解密即可
# GIF
# GIF 图片可能要分帧提取
stegsolve 可以
# Webp
webp 文件用电脑自带的图片看可能会有点问题,建议用浏览器打开这种文件
webp 可能是动图,可以用下面这个脚本分离 webp 中的每帧图片
1 2 3 4 5 6 7 from PIL import Imageimg = Image.open ('killer.webp' ) n_frame = img.n_frames for i in range (n_frame): img.seek(i) img.save(f'img/{i} .png' )
# RAW、ARW
# RAW 的 LSB 隐写
ARW 文件是 Sony 相机的原始数据格式
可以使用 rawpy 模块读取图片的像素数据,查看是否存在 LSB 隐写【例:2024 L3HCTF RAWatermark】
示例脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import rawpyimport numpy as npimport libnumwith rawpy.imread('image.ARW' ) as raw: bayer_visible = raw.raw_image_visible lsb_array = np.bitwise_and(bayer_visible, 1 ) lsb_array_flat = lsb_array.flatten() hidden_message = '' .join(map (str , lsb_array_flat)) hex_data = hex (int (hidden_message, 2 )) data = libnum.b2s(hidden_message) with open ('flag.zip' , 'wb' ) as f: f.write(data)
# 直接改后缀为.data,然后拖入 Gimp
# 二维码
# bmp 转二维码
# Aztec code、DataMatrix、GridMatrix、汉信码、PDF417code
# 二维码的纠错等级
1 位置的颜色
2 位置的颜色
纠错等级
容错率
黑
黑
L(Low)
7%
黑
白
M(Medium)
15%
白
黑
Q(Quartil)
25%
白
白
H(High)
30%
# 二维码修复