ctfshow-Misc入门 图片篇(1-49)

2023-11-01

八神出的misc入门系列

misc50及之后的题解

我这里很多题的解法是非预期,建议不懂的师傅去看八神师傅的出题思路及预期解(misc5-23)。

图片篇(基础操作)

misc1

打开图片,看到flag

misc2

下载得到misc2.txt,这是一个点,不要相信题目所给附件的后缀,用winhex打开发现是一个png文件,修改后缀为png,打开看到flag

顺便学了一下Python怎么提取图片中的文字
在这里插入图片描述

misc3

下载得到bpg文件,无法直接查看,到在线网站下载工具
在这里插入图片描述
然后查看图片
在这里插入图片描述

misc4

给了6个"txt"文件,分别用winhex打开,查看文件头,发现需要修改后缀。

依次分别改为png、jpg、bmp、gif、tif、webp
这题还是要多积累

然后把图片内容拼起来就得到flag。

图片篇(信息附加)

misc5

winhex打开,在尾部看到flag
在这里插入图片描述

misc6

和上一题差不多,不过把flag藏到了中间,我是用notepad打开,ctrl+f搜索得到的
在这里插入图片描述

misc7

这个题给提示了:flag在图片文件信息中。

直接右键查看属性是常用的方法,不过获取不到图片的全部文件信息,也得不到这题的flag

使用在线网站查看详细的exif信息

用notepad也能做
在这里插入图片描述

misc8

用winhex打开,发现图片中隐写了其他图片,手动或者binwalk或者foremost分离出图片。
在这里插入图片描述
查看图片得到flag

misc9

提示:flag在图片块里。
在这里插入图片描述
用misc6的方法也能做出来,我这里是用010editor做的。

misc10

提示:flag在图片数据里。

binwalk -e 分离出数据后
在这里插入图片描述
打开第一个文件得到flag

关于原理,八神在群里说过,我忘记截图了,这里用套神师傅博客里的图
在这里插入图片描述

misc11

提示:flag在另一张图里。

这个图有两个IDAT块,而且没有隐写其他的数据在这里插入图片描述
应该是上次八神的PNG隐写入门赛的png14一个思路,试着把第一个IDAT块的数据删除,然后另存为一张新图片,这个过程可以手动操作,也可以使用tweakpng工具。

flag:ctfshow{44620176948fa759d3eeafeac99f1ce9}

misc12

提示:flag在另一张图里。

和上题一样的提示,所以思路是一样的。

不过这题有30个IDAT块,用PNGDebugger跑了一下,发现没有出错的IDAT块…
一个一个删着试吧

测试后发现需要删掉前8个IDAT块

flag:ctfshow{10ea26425dd4708f7da7a13c8e256a73}

misc13

提示:flag位置在图片末尾。

看到提示,第一反应是notepad++打开,ctrl+f搜索ctfshow,无果…

用010editor打开,发现第二个IDAT块中有四部分疑似flag的数据(下面还有一处未截到)
在这里插入图片描述
注意到{前面那一串字符,从第一位开始,每隔一位选取一个字符,连起来就是ctfshow

测试后发现第三部分的是正确的flag

这里把这串十六进制数值复制下来,按照规律选取正确的数值

s="631A74B96685738668AA6F4B77B07B216114655336A5655433346578612534DD38EF66AB35103195381F628237BA6545347C3254647E373A64E465F136FA66F5341E3107321D665438F1333239E9616C7D"
flag=""
for i in range(0,len(s),4):
    x = int(s[i:i+2],16)
    flag += chr(x)
print(flag)

misc14

提示:flag在那张图里。

binwalk分析发现有额外数据,直接binwalk -e或者foremost分离不出来,无奈手撸在这里插入图片描述
从选中的数据开始,复制到结尾,新建为一个jpg文件
在这里插入图片描述
拿到flag:ctfshow{ce520f767fc465b0787cdb936363e694}

misc15

提示:flag被跳过去了。

winhex打开直接看到flag
在这里插入图片描述

八神师傅的解释:BMP格式的文件头里有4位字节叫作偏移量,是用来指定从哪个字节开始为实际图像数据用的。这题就是利用增大这个偏移量的方法,把冗余数据塞在了BMP头和图像数据中间的地方。因为这段数据不会被识别,所以可以说是跳过去了。

涨姿势

misc16

提示:flag在图片数据里。

binwalk -e,然后打开这个文件得到flag,原理和misc10一样(我猜的)
在这里插入图片描述

misc17

提示:flag在图片数据里。

先binwalk分析,没啥问题,然后试试zsteg
在这里插入图片描述
发现隐藏的数据,位置处于extradata:0

将数据提取出来:zsteg -E "extradata:0" /home/volcano/桌面/misc17.png > 1.txt

然后再binwalk -e把1.txt中的数据分离出来,拿到flag
在这里插入图片描述

misc18

提示:flag在标题、作者、照相机和镜头型号里。
在这里插入图片描述

misc19

提示:flag在主机上的文档名里。

在这里插入图片描述

misc20

提示:flag在评论里。

到前面用过的exif信息查看在线网站,上传图片,看到信息(谐音可还行)()
ctfshow{c97964b1aecf06e1d79c21ddad593e42}

misc21

提示:flag在序号里。

在这里插入图片描述
转字符得到hex(X&Ys)
在这里插入图片描述
发现上面有两组与XY有关的数据,中间还有https://ctf.show/和ctfshow{},应该是八神的贴心小提示,怕我们萌新找不对地方(上次做这题的时候就没注意到…)
在这里插入图片描述
根据提示hex(X&Ys),应该是要把这里的十进制数值转为十六进制,我最开始是把四段拼起来得到3902939465237161861910824528172980145261,然后转十六进制,再套上ctfshow{},然后错了…

如果不是整体直接转换的话,那么应该就是每段分别转hex,然后拼起来

最终得到:ctfshow{e8a221498d5c073b4084eb51b1a1686d}

misc22

提示:flag在图片里。
magicexif打开,直接发现flag在这里插入图片描述
原来八神是把flag藏到了缩略图中
在这里插入图片描述
我换了个颜色,方便确认
我第一遍看出来的是ctfshow{dbf7d3f84b0125e833dfd3o80820a129}

然后提交一直失败,无奈去问八神,原来这个不是o,是c
在这里插入图片描述
所以ctfshow{dbf7d3f84b0125e833dfd3c80820a129}

misc23

提示:flag在时间里。

21题搞出来了,这题就有思路了
使用exiftool看一下发现有好几个历史时间,上面的History Action中有提示在这里插入图片描述
Timestamp指的是时间戳,那个前缀没搞懂是什么意思,DECtoHEX是十进制转十六进制

这里利用在线网站获取时间戳
在这里插入图片描述
最后得到4段

874865822 2699237688 2156662245 460377706

按照21题的经验,分别hex后拼在一起

得到: ctfshow{3425649ea0e31938808c0de51b70ce6a}

misc41

提示:

H4ppy Apr1l F001’s D4y!
愚人节到了,一群笨蛋往南飞,一会儿排成S字,一会儿排成B字。

愚人节限定题,下载得到misc41.jpg,用winhex打开,发现是jpg的文件尾,但是文件头对不上,本来想以这个方向为突破点,没得到结果…

后面看了套神的wp才知道,提示中的第二句说的就是我…

第一句提示的F001才是真突破点,这个位置有大量F001,看起来组成了某种形状在这里插入图片描述
我的思路是,把F001出现过的位置中所有十六进制的值单独截取出来,每四位分隔开,把F001替换成0,其他值替换成空格。 最后变成下图的8*125的“图”,其实如果会用CyberChef会更方便,不过我不太习惯。
在这里插入图片描述

依稀看出flag:ctfshow{fcbd427caf4a52f1147ab44346cd1cdd}

图片篇(文件结构)

misc24

提示:flag在图片上面

通过这篇博客了解一下bmp文件结构

目前是900*150=135000个像素大小,文件头占了53个字节,文件尾的位置在675053字节处(后面两个字节是windows的”补0”),又因为每个像素点由3个字节(十六进制码6位)表示,每个字节负责控制一种颜色,分别为蓝(Blue)、绿(Green)、红(Red),所以文件真实的像素大小为:(675053-53)/3=225000
在这里插入图片描述
这题的宽度是对的,所以正确的高度是225000/900=250
bmp文件修改高度,借助010editor的bmp.bt模板,我这里高度改到250
在这里插入图片描述
然后就能看到flag

misc25

提示:flag在图片下面
png改图片高度还是很简单的,左框是图片宽度,右框是图片高度

把00000096改成00000196,看到下面藏的数据
在这里插入图片描述

misc26

提示:flag还是在图片下面,但到底有多下面?

仍然是png修改高度,跟上题比数字可以夸张一点
在这里插入图片描述
flag中间有一段数据是需要计算的,上网找脚本,根据图片的crc32值爆破宽高,这题算出来高度是25e

misc27

提示:flag在图片下面

根据提示,修改图片高度,看到flag
在这里插入图片描述

misc28

提示:flag在图片下面

使用gif.bt修改图片高度
在这里插入图片描述
改完从预览图中能看到flag,但是直接打开就看不到了,使用图片编辑器或者Stegsolve打开
在这里插入图片描述

misc29

提示:flag在图片下面

我把每一帧的高度都改了,最后发现在第八帧下藏了flag
在这里插入图片描述

在这里插入图片描述

misc30

提示:正确的宽度是950。

修改宽高即可
在这里插入图片描述

misc31

提示:高度是正确的,但正确的宽度是多少呢。

思路和misc24一致,最后算出宽度为1082(余数舍去)

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'))

在这里插入图片描述
把宽度修改为1044即可看到flag

misc33

提示:出题人丧心病狂,把高度也改了

还是用上题的脚本
在这里插入图片描述

misc34

提示:出题人狗急跳墙,把IHDR块的CRC也改了,但我们知道正确宽度肯定大于900

把上面的脚本稍微改一下

import zlib
import struct
filename = "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(name,"wb")
        im = all_b[:16]+struct.pack('>i',i)+all_b[20:]
        f1.write(im)
        f1.close()

把生成的所有图片都保存下来了(建议在空文件夹里),然后用眼看哪个是正常的。

最后得到正确的宽度是1123

misc35

提示:出题人负隅顽抗,但我们知道正确宽度肯定大于900

总体思路同上题,不过这题有点小坑,第一次爆破出的结果没看到flag,扩大范围之后又跑了一次还是没有,后面才知道,要把图片基础的高度调高一点,才能看到flag

import zlib
import struct
filename = "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(name,"wb")
        im = all_b[:159]+struct.pack('>h',i)+all_b[161:]
        f1.write(im)
        f1.close()

高度我调到了600,宽度在993-1000这个范围内都可以得到flag

misc36

提示:出题人坦白从宽,正确的宽度在920-950之间

吸取上题教训,先把高度调高一点
在这里插入图片描述
脚本如下:

import zlib
import struct
filename = "misc36.gif"
with open(filename, 'rb') as f:
    all_b = f.read()
    for i in range(920,951):
        name = str(i) + ".gif"
        f1 = open(name,"wb")
        im = all_b[:38]+struct.pack('>h',i)[::-1]+all_b[40:]
        f1.write(im)
        f1.close()

正确宽度是941

misc37

提示:flag在图片里

gif文件,用Stegsolve打开,一共有45帧,flag藏在9、14、21、31、34帧里

misc38

提示:flag在图片里

这个是apng图片,像gif一样会动的,用浏览器打开就知道了

可以使用APNG Disassembler来把每一帧分离出来,9、17、36、40帧中藏有flag

misc39

这题也是一个gif,不过这里是利用不同帧之间的间隔时间来隐写的。

这里利用linux下的工具identify

安装命令:sudo apt-get install imagemagick
基本的命令格式:
  identify [options] input-fileidentify:命令名称
  options:参数
  input-file:文件名。
提取命令:identify -format "%T " misc39.gif > 1.txt

得到的一串36和37,考虑把37换成1、36换成0,就得到长度为287的二进制字符串,考虑每7位转一个字符(正常是8位一组),得到flag。

s="11000111110100110011011100111101000110111111101111111011011010101100100111000011000101100101100110110011001110010111001011010111001101100010011011111000101100101011001001101100111000110010001110010110110011001111000010111001110010111000101100011110000101100000110100011010101110011111101"
flag=""
for i in range(41): #287//7
    flag += chr(int(s[7*i:7*(i+1)],2))
print(flag)

misc40

这题给了个apng,因为也是动态的,所以思路同上题。

在做misc38的时候使用了工具APNG Disassembler,当时分离出来的除了每一帧的图片外,还有一个记录了详细信息的txt文件,里面就有我们需要的信息,然后就是写脚本了。

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)

misc42

提示:flag有多长?2cm……不好意思打错了,41位

用010editor打开,发现有48个IDAT块,结合提示flag长度为41,很有可能有关联。
用tweakpng打开misc42.png,发现这七个数正好是ctfshow对应的ascii码
在这里插入图片描述
把剩下的数也转换,得到flag

misc43

提示:错误中隐藏着通往正确答案的道路

用tweakpng打开,报了一堆错,然后使用pngdebugger分析,发现所有IDAT块的crc32值都是错误的
在这里插入图片描述
结合提示,把报错的crc提取出来,hex转字符得到flag
在这里插入图片描述

misc44

提示:错误中还隐藏着坑

根据提示,可以知道还是从crc32入手,先用010editor打开,好家伙344个IDAT块
在这里插入图片描述
建议别用tweakpng打开,因为每有一个IDAT块的crc32是错误的,就会弹窗一次,这题少说得有一百来个?

这里使用PNGDebugger,用了一个小技巧

PNGDebugger.exe misc44.png > 1.txt

然后写脚本,把CRC OK的替换成1,CRC FAILED替换成0
在这里插入图片描述
使用脚本前,先把前十行无用的内容删去,再把最后四行也删去。

f=open("1.txt","r")
s=f.read()
f.close()
flag=""
for i in s.split():
    if "OK!" == i:
        flag += "1"
    elif "FAILED" ==i:
        flag += "0"
print(flag)
#11111111111111110110001101110100011001100111001101101000011011110111011101111011011000110110001100110001011000010110011000110011001100100110001001100110001110010011011000110011001100000011100001100110011000110011000100110010001101100011001100110010001100110011000101100010011001010011011100111000001100110110011000110110001110010110010101111101
print(len(flag)) #344
for i in range(43):
    print(chr(int(flag[8*i:8*(i+1)],2)),end="")

misc45

提示:有时候也需要换一换思维格式

其他题都出来了,这个题迟迟没有被解出来,我本来以为是脑洞题,十天前被bit师傅拿了一血,原来是一个新的知识点。

八神很贴心地告诉我们要换图片的格式,具体做法就是:先去在线网站把图片从png格式转为bmp格式,然后直接binwalk提取就能得到flag.png了。
在这里插入图片描述
bmp格式下,中间的位置插入了一个gzip的数据,直接肉眼看很难看出来,至于为什么原本的png格式下,binwalk得不到结果呢?大师傅们的解释是png和bmp像素点的读取方式不一样
在这里插入图片描述

misc46

是一个gif

提取出它的详细信息:identify misc46.gif > /1.txt (这里直接在根目录生成1.txt,好找)

内容大概长这样,其中0+0174+49196+47这些是偏移量,这题就利用这个来作图。
在这里插入图片描述
写一个很简单的脚本把坐标提取出来

f = open("1.txt","r")
x = f.readlines()
f.close()

f = open("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()

再利用gnuplot作图,画出来的结果有点模糊,自行调整
在这里插入图片描述
再翻转一下得到flag

misc47

给了一个png,打开发现没内容,用浏览器打开,确认是apng

思路和上题一致,不过稍微复杂一点,先通过这篇文章了解一下apng文件结构,简单来说就是每一个IDAT块前面都会有一个fcTL块,它其中就包含水平垂直偏移量

如下,对应坐标点就是(182,52)
在这里插入图片描述
之前的脚本有的师傅使用的时候有点小问题,所以改了一下

from PIL import Image

im = Image.new('RGB', (400, 80), 255)
f = open('1.txt','r') #把图片的十六进制导出,保存为1.txt
c = f.read()
f.close()

lt = c.split("6663544C")
for i in range(2,len(lt)):
    x = int(lt[i][28:32],16)
    y = int(lt[i][36:40],16)
    im.putpixel((x,y),0)  
im.show()

misc48

用010editor打开,发现有提示

1、统计FF的数量,再减去1
2、ctfshow{}中包含32个字符

在这里插入图片描述
提示了,但没有完全提示,因为第一条提示,其实指的是统计每两个有意义块之间的FF的数量再减一

图中紫色的就是,开头的那个FF也算,因为只有一个,减去1后就是0;接下来是12110
在这里插入图片描述
因为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

分别转十六进制后,再连接在一起,得到:ctfshow{0cb07add909d0d60a92101a8b5c7223a}

misc49

提示:它们一来就是十六种。本题略脑洞,可跳过

八神的脑洞题,靠我自己想是不行的,果断参考wp

用winhex打开,能看到很多字符串,这其实是八神给的提示,虽然我没get到
在这里插入图片描述
重点是这些字符串前面,都出现过FFE? 这种格式的数据,搜索一下发现有挺多的
在这里插入图片描述

把所有十六进制数保存在2.txt中,用一个小脚本处理一下

f=open("2.txt","r")
txt=f.read().replace("\n","")
f.close()

l=txt.split("FFE")
flag=""
for i in range(1,len(l)):
    flag += l[i][0]
print(flag.lower()[:32]) #得到的结果套上ctfshow{}

其实就是把FFE后面的那个字符提取出来,再连接在一起,一共32位(),这就是flag。

这里写脚本的时候有个小失误,把这种也统计进去了,所以只有前32位是符合格式的正确的。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ctfshow-Misc入门 图片篇(1-49) 的相关文章

随机推荐