赞
踩
后续提取图片中的flag均为脚本提取,部分flag提取出错需要人工再次核验哈~,flag提取演示
flag在下载的图片上
将后缀名改为
.png
即可在图片上看到flag
推荐一款图片浏览器
Honeyview
,直接可以查看bpg格式的图片
用 HxD 依次查看文件头,将后缀名依次改为
.png
、.jpg
、.bmp
、.gif
、.tif
、.webp
,将内容拼接起来即可得到flag
用
HxD
打开,拖到尾部即可发现flag
用
HxD
打开,搜索关键词ctfshow
即可发现flag
用
HxD
打开,搜索关键词ctfshow
即可发现flag
binwalk
查看图片发现隐藏图片,利用foremost
提取出来
用
zsteg
查看图片,发现flag
zsteg安装方法 (补充)
更换RubyGems的源
gem sources --remove https://rubygems.org/
gem sources --add https://gems.ruby-china.com/
gem sources -l
安装zsteg
git clone https://hub.fastgit.org/zed-0xff/zsteg.git
cd zsteg
gem install zsteg
zsteg的使用方法 (常见)
查看帮助 zsteg -h 查看LSB信息 zsteg pcat.png 检测zlib # -b的位数是从1开始的 zsteg zlib.bmp -b 1 -o xy -v 显示细节 zsteg pcat.png -v 尝试所有已知的组合 zsteg pcat.png -a 导出内容 zsteg -E "b1,bgr,lsb,xy" pcat.png > p.exe 更多的使用方法可以查看README.md
用
binwalk
查看图片,分离图片,查看数据块即可发现flag,需要注意的是zlib是PNG IDAT的可选压缩格式
binwalk 查看发现两个IDAT数据块,尝试删去第一个数据块,查看图片发现flag
zsteg查看图片提示数据块异常
测试后发现需要删掉前8个IDAT块
HxD
查看发现图片尾部存在可疑数据,观察发现{
前面那一串字符从第一位开始每隔一位选取一个字符,连起来就是ctfshow,编写脚本提取flag
s="631A74B96685738668AA6F4B77B07B216114655336A5655433346578612534DD38EF66AB35103195381F628237BA6545347C3254647E373A64E465F136FA66F5341E3107321D665438F1333239E9616C7D"
flag=""
for i in range(0,len(s),4):
flag += s[i]
flag += s[i+1]
print(flag)
binwalk
查看图片,发现JPEG图片,foremost
和binwalk
无法成功提取,用HxD
打开搜索文件头手动提取
用
HxD
打开搜索关键词ctfshow
即可发现flag
binwalk
查看图片,发现额外数据,用binwalk -e
提取出来,查看提取出来的文件发现flag
binwalk
提取出来的东西解不出,尝试zsteg
,根据提示提取信息得到PNG图片,查看图片发现flag
用
exiftool
查看图片,flag在标题、作者、照相机和镜头型号里
用
exiftool
查看图片,flag在主机上的文档名里
用
exiftool
查看图片,flag在评论里
用
exiftool
查看图片,将序列号686578285826597329
转字符得到hex(X&Ys)
,分别将X/Y Resolution
和X/Y Position
转成hex,然后拼接起来,flag为ctfshow{e8a221498d5c073b4084eb51b1a1686d}
直接查看图片没有发现什么,但是用
Honeyview
浏览缩略图时发现数据
利用
MagicEXIF
查看图片,flag为ctfshow{dbf7d3f84b0125e833dfd3c80820a129}
用
exiftool
看一下发现有好几个历史时间,History Action
中有提示
将给出的四个时间的时间戳转换出来,分别hex后拼在一起,转换地址
提示中的
F001
是突破点,HxD
查看图片发现有有大量F001
组成了某种形状
把
F001
出现过的位置中所有十六进制的值单独截取出来,每四位分隔开,把F001替换成0,其他值替换成空格,得到一张含有flag的图片,这里也可以采用CyberChef
来解决问题,flag为ctfshow{fcbd427caf4a52f1147ab44346cd1cdd}
用
HxD
查看一下图片,文件头占了53个字节,文件尾的位置在675053字节处 (后面两个字节是windows的”补0”),因为每个像素点由3个字节 (十六进制码6位) 表示,每个字节负责控制一种颜色,分别为蓝(Blue)、绿(Green)、红(Red),所以文件真实的像素大小为:(675053-53)/3=225000
题目给的图片是
900*150=135000
个像素大小
尝试后发现这题的宽度是对的,所以正确的高度是
225000/900=250
,将高度改成
用
TweakPNG
查看图片发现图片的CRC值不对,猜测应该是修改了宽高,用脚本跑一下看看
根据脚本计算出来的值修改宽高,保存后即可看到flag
用
TweakPNG
查看图片发现图片的CRC值不对,和上一题一样用脚本跑一下看看
根据脚本计算出来的值修改宽高,保存后即可看到flag
根据提示,猜测依旧是修改图片高度,将高度改高后即可发现flag
根据提示,猜测依旧是修改图片高度,将高度改高后即可发现flag,但是需要注意从预览图中能看到flag,但是直接打开看不到,可以使用图片编辑器或者Stegsolve打开
GIF有很多帧,将每一帧的高度都改高后,用
Stegsolve
查看,在第八帧即可发现flag
根据提示修改BMP图片宽度即可发现flag
根据题给描述,计算正确宽度
根据题给描述,计算出正确的高宽
import zlib import struct # 同时爆破宽度和高度 filename = "misc32.png" with open(filename, 'rb') as f: all_b = f.read() data = bytearray(all_b[12:29]) n = 4095 for w in range(n): width = bytearray(struct.pack('>i', w)) for h in range(n): height = bytearray(struct.pack('>i', h)) for x in range(4): data[x+4] = width[x] data[x+8] = height[x] crc32result = zlib.crc32(data) #替换成图片的crc if crc32result == 0xE14A4C0B: print("宽为:", end = '') print(width, end = ' ') print(int.from_bytes(width, byteorder='big')) print("高为:", end = '') print(height, end = ' ') print(int.from_bytes(height, byteorder='big'))
修改宽高保存后即可看到flag
根据题给描述,计算出正确的高宽
修改宽高保存后即可看到flag
利用脚本把生成的所有图片都保存下来了,观察哪个是正常的
import zlib
import struct
filename = r"C:\Users\95235\Downloads\misc34\misc34.png"
with open(filename, 'rb') as f:
all_b = f.read()
#w = all_b[16:20]
#h = all_b[20:24]
for i in range(901,1200):
name = str(i) + ".png"
f1 = open(r"C:\Users\95235\Downloads\misc34\\" + name,"wb")
im = all_b[:16]+struct.pack('>i',i)+all_b[20:]
f1.write(im)
f1.close()
先把图片基础的高度调高一点(高度在600,宽度在993-1000这个范围内都可以得到flag),才能看到flag
import zlib
import struct
filename = r"C:\Users\95235\Downloads\misc35\misc35.jpg"
with open(filename, 'rb') as f:
all_b = f.read()
#w = all_b[159:161]
#h = all_b[157:159]
for i in range(901,1200):
name = str(i) + ".jpg"
f1 = open(r"C:\Users\95235\Downloads\misc35\\" + name,"wb")
im = all_b[:159]+struct.pack('>h',i)+all_b[161:]
f1.write(im)
f1.close()
和上一题一样先把图片基础的高度调高一点,脚本爆破即可,用照片编辑器查看gif文件
import zlib
import struct
filename = r"C:\Users\95235\Downloads\misc36\misc36.gif"
with open(filename, 'rb') as f:
all_b = f.read()
for i in range(920,951):
name = str(i) + ".gif"
f1 = open(r"C:\Users\95235\Downloads\misc36\\" + name,"wb")
im = all_b[:38]+struct.pack('>h',i)[::-1]+all_b[40:]
f1.write(im)
f1.close()
用
Stegsolve
查看,flag在8、14、21、31、34
帧中,拼接起来即可
题目所给的是apng图片,可以使用APNG Disassembler来把每一帧分离出来,
9、17、36、40
帧中藏有flag
这里是利用不同帧之间的间隔时间来隐写的,利用
identify
来处理该GIF图片
安装命令:
sudo apt-get install imagemagick
提取命令:
identify -format "%T " misc39.gif > 1.txt
,得到的一串36和37
把37换成1、36换成0,得到长度为287的二进制字符串,由于无法整除8,考虑7位一组,转换成字符得到flag
文件识别为
apng
文件,使用工具APNG Disassembler
,flag在记录详细信息的txt文件中,用脚本把flag提取出来
根据提示,用
tweakpng
打开图片,发现IDAT块的长度很可疑,有一部分IDAT块的长度转换为字符是ctfshow
,将后面的接着转换成字符即可得到flag
根据题给描述,先用tweakpng打开分析一下图片,发现报了一堆错,使用
pngdebugger
分析,发现所有IDAT块的crc32值都是错误的
将错误的IDAT块的
crc-code
提取出来,拼接起来转字符串即可得到flag
import binascii
def hex_to_str(s):
hex = s.encode('utf-8')
str_bin = bin
str_bin = binascii.unhexlify(hex)
return str_bin.decode('utf-8')
s = 'E59387E593A62E63746673686F777B36656232353839666666663565333930666536623837353034646263303839327D'
hex_to_str(s)
根据提示,用
PNGDebugger
打开,把信息导入到txt文件中
利用脚本把
CRC OK
的替换成1,CRC FAILED
替换成0,注意先把前十行的内容删去,再把最后四行删去
根据题给描述,猜测是文件转换,测试后发现转成
.bmp
格式后,用binwalk
提取即可,看大师傅的blog发现考察点是png和bmp像素点的读取方式
根据题给描述,搜索后猜测应该是画图之类的,先提取出GIF的详细信息
identify misc46.gif > message.txt
观察得到的信息,其中
0+0、174+49、196+47
这些是偏移量,用其来进行画图
坐标提取:
f = open(r"C:\Users\95235\Downloads\misc46\message.txt","r")
x = f.readlines()
f.close()
f = open(r"C:\Users\95235\Downloads\misc46\out.txt","w")
for i in x:
f.write(i.split("+")[1])
f.write(" ")
f.write(i.split("+")[2][:2])
f.write("\n")
f.close()
根据得到的点坐标进行绘图
测试后发现是apng格式,解题的思路是根据每一个IDAT块前面的一个fcTL块中包含的水平垂直偏移量
import struct from PIL import Image import matplotlib.pyplot as plt f = open(r'C:\Users\95235\Downloads\misc47\misc47.png','rb') c = f.read() c = c[c.index(bytes.fromhex('6663544C00000001')):] pp = [] for i in range(1,1124,2): start = c.index(bytes.fromhex('6663544C0000')+struct.pack('>h',i)) fc = c[start:start+30] print(fc[18:20],fc[22:24]) print(struct.unpack('>h',fc[18:20])+struct.unpack('>h',fc[22:24])) pp.append(struct.unpack('>h',fc[18:20])+struct.unpack('>h',fc[22:24])) img = Image.new('RGB',(400,70),(255,255,255)) for i in pp: new = Image.new('RGB',(1,1),(0,0,0)) img.paste(new,i) plt.imshow(img) plt.show()
用
010 editor
打开,发现提示统计FF的数量再减去1、ctfshow{}中包含32个字符
因为flag长度是32位,所以只需要统计前32个段就行
0 12 11 0 7 10 13 13 9 0 9 13 0 13 6 0 10 9 2 1 0 1 10 8 11 5 12 7 2 2 3 10
分别转换成hex即可
s = [0,12,11,0,7,10,13,13,9,0,9,13,0,13,6,0,10,9,2,1,0,1,10,8,11,5,12,7,2,2,3,10]
f = '0123456789abcdef'
flag = 'ctfshow{'
for i in range(len(s)):
flag += f[s[i]]
flag += '}'
print(flag)
用
010 editor
打开,FFE
后面的就是flag的值
由于是颜色通道篇的,很自然想到用
Stegsolve
查看一下,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。