ctfshow-MISC入门
图片篇(基础操作)
misc1
下载压缩包->解压->打开图片直接拿到flag
misc2
头文件是PNG->改后缀.png->拿到flag
misc3
下载:软件,打开->拿到flah
misc4
下载拿到6个.txt
文件,将他们放到010 editor中,得到他们后缀名分别是.png
,.jpg
,.BMP
,.gif
,.tif
,.webp
->拼接在一起拿到flag
总结:(文件头判断文件类型)
JPEG (jpg) 文件头:FF D8 FF 文件尾:FF D9
PNG (png),文件头:89504E47
Windows Bitmap (bmp), 文件头:424D
GIF (gif),文件头:47494638
XML (xml),文件头:3C3F786D6C
HTML (html),文件头:68746D6C3E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0
MS Access (mdb),文件头:5374616E64617264204A
Adobe Acrobat (pdf),文件头:255044462D312E
Windows Password (pwl),文件头:E3828596
ZIP Archive (zip),文件头:504B0304
RAR Archive (rar),文件头:52617221
Wave (wav),文件头:57415645
AVI (avi),文件头:41564920
TIFF (tif), 文件头:49492A00
图片篇(信息附加)
misc5
解压图片发现没有flag
放入010 editor中,在最后拿到flag
misc6
解压图片发现没有flag
放入010 editor中,在ctrl+F搜索ctf,拿到flag
misc7
题目提示:flag在图片文件信息中。
同上
misc8
题目提示:flag在图片文件中图片文件中。
解压图片发现没有flag
使用foremost
分离
发现里面有两张图片 其中一张就是flag
misc9
题目提示:flag在图片块里
解压图片发现没有flag
放入010 editor中,在ctrl+F搜索ctf—>拿到flag
misc10
题目提示:flag在图片数据里
解压图片发现没有flag
binwalk分析图片结构—>分离出含有隐藏的zlip信息
10ES就是flag
misc11
题目提示:flag在另一张图里。
解压图片发现没有flag
使用Tweakpng工具,把第二个 IDAT
数据删除->保存->重新打开图片
拿到flag
misc12
题目提示:flag在另一张图里。
解压图片发现没有flag
和上题一样,但是这题有30个IDAT块,用PNGDebugger跑了一下但是发现没有出错的IDAT块
扩充:
PNG Debugger 可以进行读取 PNG 图片的数据,检测各数据块中的 CRC 是否正确,在 Windows 下使用。
CRC 码是 循环冗余校验码 的简称,是 png 图片中一种的数据, 是目前使用非常广泛的数据校验方式,不仅能校验传递过来的数据正确性,还能筛查出哪一位出现了错误。
比如可用于判断 png 图片的宽和高是否正确。
pngdebugger使用方法:https://blog.csdn.net/Goodric/article/details/119732559
需要删除前8个IDAT块,拿到flag
misc13
题目提示:flag位置在图片末尾。
解压图片发现没有flag
前面那一串字符,从第一位开始,每隔一位选取一个字符,连起来就是ctfshow
这里把这串十六进制数值复制下来,按照规律选取正确的数值
脚本:
a="631A74B96685738668AA6F4B77B07B216114655336A5655433346578612534DD38EF66AB35103195381F628237BA6545347C3254647E373A64E465F136FA66F5341E3107321D665438F1333239E9616C7D"
flag=""
for i in range(0,len(a),4):
hexStr=a[i:i+2]
flag+=chr(int("0x"+hexStr,16))
print(flag)
拿到flag
misc14
题目提示:flag在那张图里。
解压图片发现没有flag
先使用binwalk -e
分离出来
然后使用dd
,从binwalk分析出来的数据位置截取数据。可以看到起始地址为2103,输入命令
dd if=misc14.jpg of=flag.jpg skip=2103 bs=1
然后会在当前目录下生成一个1.png文件,打开即可
其中if=misc14.jpg是输入文件,of=1.png是输出文件,skip是指定从输入文件开头跳过2103个块后再开始复制,bs设置每次读写块的大小为1字节 。
拿到到flag
。
misc15
题目提示:flag被跳过去了。
解压图片发现没有flag
打开010 editor拿到flag
misc16
题目提示:flag在图片数据里。
解压图片发现没有flag
使用binwalk命令分离
打开DD4->拿到flag
misc17
题目提示:flag在图片数据里。
解压图片发现没有flag
binwalk分析得出有一个bzip,但是什么都分离不出来
使用zsteg
zsteg工具:用于检测被隐写在png,bmp图片里的数据。
发现隐藏的数据,位置处于extradata:0;有3544 bytes的隐写内容
将数据提取出来:
zsteg -E "extradata:0" misc17.png > 1.txt
然后再binwalk -e把1.txt中的数据分离出来
binwalk -e 1.txt
拿到flag
misc18
题目提示:flag在标题、作者、照相机和镜头型号里。
解压图片发现没有flag
通过在线网站查看详细的exif信息
拿到flag
misc19
题目提示:flag在主机上的文档名里。
同18关查看详细的exif信息->拿到flag
misc20
题目提示:flag在评论里。
同18关查看详细的exif信息
读出来便拿到flag
misc21
题目提示:flag在序号里。
同上
分别将X分辨率,Y分辨率,X定位,Y定位进行hex转换
拿到flag:ctfshow{e8a221498d5c073b4084eb51b1a1686d}
misc22
题目提示:flag在图片里。
使用工具exiftool 参考文献:https://www.rmnof.com/article/exiftool-introduction/
exiftool -ThumbnailImage -b misc22.jpg > 1.jpg
拿到flag
misc23
题目提示:flag在时间里。
使用exiftool来查看
exiftool misc23.psd
UnixTimestamp, DECtoHEX, getflag
Timestamp是指时间戳,DECtoHEX是将十进制转十六进制
1997:09:22 02:17:02+08:00, 2055:07:15 12:14:48+08:00, 2038:05:05 16:50:45+08:00, 1984:08:03 18:41:46+08:00
+08:00是转换为北京时间的意思
UTC是国际时,UTC+8就是国际时加八小时,是东八区时间,是北京时间。
GMT就是指格林尼治所在地的标准时间,+8:00就是东八区的时间,即北京时间。
将四段时间转换完成后->转换为16进制->拼凑后->拿到flag
ctfshow{3425649ea0e31938808c0de51b70ce6a}
misc41
题目提示:H4ppy Apr1l F001’s D4y! 愚人节到了,一群笨蛋往南飞,一会儿排成S字,一会儿排成B字。
用010 editor打开,搜索f001
,搜索类型换位16进制字节
看背景拿到flag
图片篇(文件结构)
知识点:
用tweakpng打开发现CRC校验错误,说明要改宽高了
修改png,jpg,gif,bmp四种图片文件的宽高
png: 前四位是宽,后四位是高
jpg: 前两位是高,后两位是宽
bmp:前四位是宽,后四位是高,但是是倒着写
03 B6———>写成B6 03先打开属性,确定目前宽高数据,再转换成十六进制在010 editor中找
misc24
题目提示:flag在图片上面。
用010editor查看文件,点击信息块,发现大小为675000字节,除以3(代表3个颜色),(675053-53)/3=225000。用225000除以高度900,得到宽度为250转十六进制得FA,所以将高度改成 FA
拿到flag
misc25
题目提示:flag在图片下面。
使用 TweakPNG
查看图片发现图片的CRC
值错误
通过脚本算出长和宽的正确值
import binascii
import struct
crcbp = open("misc25.png", "rb").read() #打开图片
crc32frombp = int(crcbp[29:33].hex(),16) #读取图片中的CRC校验值
print(crc32frombp)
for i in range(4000): #宽度1-4000进行枚举
for j in range(4000): #高度1-4000进行枚举
data = crcbp[12:16] + \
struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]
crc32 = binascii.crc32(data) & 0xffffffff
# print(crc32)
if(crc32 == crc32frombp): #计算当图片大小为i:j时的CRC校验值,与图片中的CRC比较,当相同,则图片大小已经确定
print(i, j)
print('hex:', hex(i), hex(j))
exit(0)
在010 editor修改值
拿到flag
misc26
题目提示:flag还是在图片下面,但到底有多下面?
同25关,用脚本跑出正确的值
修改正确的高
拿到flag
misc27
题目提示:flag在图片下面
根据题目提示,说明是图片的宽被隐写,所以增加图片的宽度(250)
拿到flag
misc28
题目提示:flag在图片下面。
把GIF每一帧的高度都由9600
改为FF00
拿到flag
misc29
题目提示:flag在图片下面。
把GIF每一帧的高度都由9600
改为FF00
使用Stegsolve 打开
拿到flag
misc30
题目提示:正确的宽度是950。
按照提示修改高度
拿到flag
misc31
题目提示:高度是正确的,但正确的宽度是多少呢。
文件头共53
个字节
所有字节是487253
,而RGB
每个像素由3
个字节表示
所以得到图片的宽度
a=(487256-54)/ 3
a=a/150 #图片的高是150
print(a) #得到图片的宽
修改宽度
拿到flag
misc32
题目提示:高度是正确的,但正确的宽度是多少呢
用脚本爆破出图片正确的宽和高
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'))
在010上修改,拿到flag
misc33
题目提示:出题人丧心病狂,把高度也改了
脚本爆破拿到正确的高和宽
import binascii
import struct
crcbp = open("misc33.png", "rb").read() # 打开图片
crc32frombp = int(crcbp[29:33].hex(), 16) # 读取图片中的CRC校验值
print(crc32frombp)
for i in range(4000): # 宽度1-4000进行枚举
for j in range(4000): # 高度1-4000进行枚举
data = crcbp[12:16] + \
struct.pack('>i', i) + struct.pack('>i', j) + crcbp[24:29]
crc32 = binascii.crc32(data) & 0xffffffff
# print(crc32)
if (crc32 == crc32frombp): # 计算当图片大小为i:j时的CRC校验值,与图片中的CRC比较,当相同,则图片大小已经确定
print(i, j)
print('hex:', hex(i), hex(j))
exit(0)
010修改
拿到flag
misc34
题目提示:出题人狗急跳墙,把IHDR块的CRC也改了,但我们知道正确宽度肯定大于900
利用脚本把生成的所有图片都保存下来
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()
一页一页找->拿到flag
misc35
题目提示:出题人负隅顽抗,但我们知道正确宽度肯定大于900
先修改图片的高度和宽度,否则看不到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()
拿到flag
misc36
题目提示:出题人坦白从宽,正确的宽度在920-950之间
同35关
首先将照片的每一帧高度调高
用脚本爆破
import zlib
import struct
filename = r"E:\桌面\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"E:\桌面\misc36.gif" + name,"wb")
im = all_b[:38]+struct.pack('>h',i)[::-1]+all_b[40:]
f1.write(im)
f1.close()
拿到flag
misc37
题目提示:flag在图片里
用Stegsolve
查看
拿到flag
misc38
题目提示:flag在图片里
使用Honeyview
拿到flag
misc39
题目提示:flag就像水,忽快忽慢地流
利用不同帧之间的间隔时间来隐写的,利用identify
来处理该GIF图片
安装命令:
sudo apt-get install imagemagick
identify -format "%T " misc39.gif > 1.txt
得到一串数字
将36转换为0,37转换为1,得到长度为287的二进制字符串,由于无法整除8,所以考虑7位一组
1100011 1110100 1100110 1110011 1101000 1101111 1110111 1111011 0110101 0110010 0111000 0110001 0110010 1100110 1100110 0111001 0111001 0110101 1100110 1100010 0110111 1100010 1100101 0110010 0110110 0111000 1100100 0111001 0110110 0110011 1100001 0111001 1100101 1100010 1100011 1100001 0110000 0110100 0110101 0111001 1111101
转成字符拿到flag
misc40
题目提示:flag就像歌,有长有短仿佛岁月悠悠
文件识别为apng
文件,用工具 APNG Disassembler可以进行分离,下载链接:APNG Disassembler download | SourceForge.net
flag在记录详细信息的txt文件中,用脚本把flag提取出来
flag=""
for i in range(28,69): #flag内容从28位开始
f = open('apngframe'+str(i)+'.txt')
s = f.read()
flag += chr(int(s.split("/")[0][6:]))
print(flag)
拿到flag
misc42
题目提示:flag有多长?2cm……不好意思打错了,41位
TweakPNG
打开查看IDAT
块 将长度进行chr
转换
a = [229, 152, 191, 229, 152, 191, 49, 99, 116, 102, 115, 104, 111, 119, 123, 48, 55, 56, 99, 98, 100, 48, 102, 57, 99,56, 100, 51, 102, 50, 49, 53, 56, 101, 55, 48, 53, 50, 57, 102, 56, 57, 49, 51, 99, 54, 53, 125]
for i in a:
print(chr(i),end='')
拿到flag
misc43
题目提示:错误中隐藏着通往正确答案的道路
使用tweakpng分析一下图片,发现报了一堆错
pngdebugger使用方法:https://blog.csdn.net/Goodric/article/details/119732559
将错误的IDAT
块的crc-code
提取出来,拼接起来
E59387E593A62E63746673686F777B36656232353839666666663565333930666536623837353034646263303839327D
十六进制转字符串,拿到flag
misc44
题目提示:错误中还隐藏着坑
用PNGDebugger
打开,把信息导入到txt文件中
pngdebugger ../misc44.png >1.txt
利用脚本把CRC OK
的替换成1,CRC FAILED
替换成0
import re
import binascii
s = open("1.txt", "r").read()
data_s = re.findall(r'\(1152\).*?CRC ([FAILED,OK!]+)', s,
re.DOTALL) # 匹配(1152)所在的段,直到结尾为FAILED或者OK!结束,在默认情况下.的作用是匹配除了换行符以外的所有字符,这里的re.DOTALL的作用是可以将. 匹配所有换行符
print(data_s)
flag = ""
for i in data_s:
if i == 'OK!':
flag += '1'
else:
flag += '0'
print(flag)
print(len(flag))
for i in range(43):
print(chr(int(flag[8*i:8*(i+1)],2)),end="")
拿到flag
misc45
题目提示:有时候也需要换一换思维格式
根据题目提示猜测是文件转换,在线转成.bmp格式后
用binwalk
提取即可,拿到flag
misc46
题目提示:你见过扶乩吗
通过identify查看它的偏移量,提取出GIF的详细信息
identify misc46.gif > message.txt
提取它每次偏移的值当做坐标,再作图
脚本:
import re
import matplotlib.pyplot as plt
from PIL import Image
f = open("message.txt", "r")
s = f.read()
# 正则表达式寻找偏移量
data_s = re.findall(r'GIF .*?\+(\d+)\+(\d+)', s, re.DOTALL)
# 将data_s里的坐标从str类型转换成int类型,不然后面的坐标不能识别
data_s = [[int(i) for i in j] for j in data_s]
# 创建一个新的RGB图像,大小为400*70的像素,背景颜色为白色(RGB的值为(255,255,255))
img = Image.new('RGB', (400, 100), (255, 255, 255))
# 创建一个新的RGB图像,大小为1*1的像素,背景颜色为黑色(RGB的值为(0,0,0))
new = Image.new('RGB', (1, 1), (0, 0, 0))
# 循环每次的坐标
for i in data_s:
# 将new(黑色像素点)粘贴到img(白色像素点)上,相当于填充
img.paste(new, i)
# 显示img图像
plt.imshow(img)
# 显示窗口以查看图像
plt.show()
拿到flag
图片篇(颜色通道)
misc50
题目提示:有时候视线也要放低一点
使用Stegsolve
查找
拼接拿到flag。
misc51
题目提示:你会数数吗。
还是先用stegsolve看一遍,没有发现,上脚本
from PIL import Image
im=Image.open('misc51.png')
im = im.convert('RGB')
img = Image.new("RGB",(900,150))
dic = {}
for h in range(900):
for w in range(150):
s = im.getpixel((h,w))
dic[s] = dic.get(s,0)+1
lt = list(dic.items())
lt.sort(key = lambda x:x[-1])
print(lt)
脚本2
from PIL import Image
im=Image.open('misc51.png')
im = im.convert('RGB')
img = Image.new("RGB",(900,150))
for h in range(900):
for w in range(150):
s = im.getpixel((h,w))
if s == (64, 96, 128) or s == (128, 96, 64):
img.putpixel([h, w], (255, 255, 255))
img.show()
拿到flag
misc52
题目提示:不会数数没关系,这次可以用眼睛瞪
和上题差不多,用脚本
from PIL import Image
im=Image.open('misc52.png')
im = im.convert('RGB')
img = Image.new("RGB",(900,150))
lt = [(130, 176, 116),(72, 217, 123),(146, 16, 141),(130, 241, 105),(251, 160, 136),(5, 129, 88),(167, 46, 187),(20, 65, 141),(96, 231, 225),(196, 144, 18)]
for h in range(900):
for w in range(150):
s = im.getpixel((h,w))
if s in lt:
img.putpixel([h, w], (255, 255, 255))
img.show()
拿到flag
misc53
题目提示:开始愉快的LSB部分。
使用工具Stegsolve
RGB
通道除第一个外都设置为0
拿到flag
misc54
题目提示:还是愉快的LSB部分。
和上一题一样使用工具Stegsolve
查看,但是需要调整一下参数
拿到flag
misc55
题目提示:怎么又是愉快的LSB部分。
这里的图片是反过来的 使用Stegsolve
发现通道存在隐写但是提取不了,所以需要把照片翻过来,脚本:
from PIL import Image
img = Image.open('misc55.png')
img.transpose(Image.FLIP_TOP_BOTTOM).save('out.png')
发现是PK
头 保存bin
将上一步保存的bin解压即可拿到flag
misc56
题目提示:怎么老是愉快的LSB部分。
使用工具Stegsolve
R4、R2、R1、G4、G2、G1
通道有隐写
拿到flag