ctfshow-Misc入门 图片篇(50-60)
Posted z.volcano
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ctfshow-Misc入门 图片篇(50-60)相关的知识,希望对你有一定的参考价值。
八神出的misc入门系列
misc57-59做的比较晚了,本来想着等解了misc61一块发wp的,忙着比赛和推免就忘了。今天看到群里有人用g4👴的工具一把梭了才想起来这个事,misc61等能把原理讲清楚了再发
图片篇
图片篇(颜色通道)
misc50
考察Stegsolve
的使用
flag:ctfshow84470883ee1eec2e886436461bf79111
misc51
提示:你会数数吗。
背景颜色杂乱无章,各个通道看了也没有思路,后面八神师傅提示了一下大致方向,才顺利解出来
统计一下每种颜色像素点的个数,发现绝大多数颜色只出现过1-3次,而(64, 96, 128)
出现过282
次,(128, 96, 64)
出现过279
次
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)
思路清晰了,Image.new
新建一个黑色背景的图像,再遍历一次,如果坐标(x,y)
对应的颜色为上述两种其一,则把该坐标对应的像素点变成白色
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()
misc52
提示:不会数数没关系,这次可以用眼睛瞪。
和上一题不一样的地方在于,在某些通道可以依稀看到flag
大概做法和misc51一样,但是不同的是,这题颜色的出现更有规律,每种颜色的出现次数在199-585
次
八神师傅非常贴心,这里只要选择出现次数最少的十种
即可,不需要猜或是爆破
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()
misc53
提示:开始愉快的LSB部分。
关于LSB隐写的基本概念可以参考LSB隐写(最低有效位隐写)
在做题时,如果遇到图片是png
或bmp
格式,就有可能是LSB隐写
大多数情况下,可以用zsteg
一把梭
但是如果出题人稍加操作,就梭不出来了,所以还是得学会使用stegsolve
在R0
、B0
、G0
通道都发现lsb隐写痕迹
使用Analyse
中的data extract
,选上对应选项
misc54
提示:还是愉快的LSB部分。
这个题就没办法用zsteg一把梭,使用stegsolve
分析
在Alpha0
、B0
、G0
通道均发现lsb隐写痕迹,而且和misc53不同的是,这里是竖向排列的,即按列(column
)
勾选上对应选项
misc55
提示:怎么又是愉快的LSB部分。
R0、G0、B0通道均有隐写痕迹,但是提取不出有用信息。
注意到图片是上下翻转的,写脚本把图片翻转回来
from PIL import Image
img = Image.open('misc55.png')
img.transpose(Image.FLIP_TOP_BOTTOM).save('out.png')
接着可以正常提取出数据,解压拿flag
misc56
提示:怎么老是愉快的LSB部分。
R4、R2、R1、G4、G2、G1通道有隐写痕迹
misc57
没完没了的LSB部分。
提示:本题附件使用可耻的手段对使用zsteg的朋友进行了阻挠。
57和58是专门针对常用工具zsteg和stegsolve而出的,目的是为了让大家了解工具背后的原理,而不是只会用工具。
参考文章:LSB隐写工具对比(Stegsolve与zsteg)
文章中较为详细地介绍了两种工具的区别。
这里简单概括一下就是:
1.字节顺序(一个字节有8bit数据,从高位开始读还是从低位开始读的顺序)
Stegsolve支持从高位开始(MSBFirst)和从低位开始(LSBFirst)
zsteg只能从高位开始读,对应Stegsolve的MSBFirst
2.组合顺序
zsteg的--lsb和--msb决定了组合顺序
--lsb:大端存放
--msb:小端存放
Stegsolve只支持大端存放,对应zsteg的—lsb
这样来看,八神师傅出题时应该是从低位开始的,这样就起到了绕过zsteg的作用。
R、G、B plane的0-3通道都有隐写痕迹,确定了LSBFirst
,还需要测试一下是哪个颜色顺序。
没有看到明显的flag格式,不过顺序为GBR时,看到了zlib
文件头(789c
)
导出后,binwalk -e解压一下即可
misc58
提示:本题附件使用可耻的手段对使用zsteg的朋友进行了阻挠。
这题绕过的是stegsolve,结合前面说到的,可以猜测这题是小端存放。
但是直接zsteg -a
或是直接指定--msb
都是梭不出来的。
又想到之前做misc56时,R4、R2、R1、G4、G2、G1通道有隐写痕迹,但是没想明白怎么用zsteg获取指定数据,看完前面介绍的文章大概理清楚了。
zsteg -a 默认只会读取b1-b8,而misc56对应的是b22,所以梭不出来
此时需要自己控制参数来查看,如这里涉及到RB两种组合,利用-c参数即可
比如zsteg -c r4g3 ,就是r通道的低4bit、g通道的低3bit
若-c 设置的rgbr不加数字,则表示每个通道读取bit数相同,借助-b设置具体bit数
例如zsteg -c rg -b 10110 ,表示读取R4、R2、R1、G4、G2、G1通道
因此,对于misc56,用zsteg解题的话,命令为:
zsteg misc56.png -c rg -b 10110 -v
10进制或是16进制表示也可
zsteg misc56.png -c rg -b 22 -v
zsteg misc56.png -c rg -b 0x16 -v
知道这些就可以解misc58了,因为R3、R2、R1、B3、B2、B1通道有隐写痕迹,小端存放。
那么,这题的命令应该为:
不过不知道为什么我-E导出时报错,所以带上-v查看zlib文件的hex,手动提取保存出来,再binwalk -e提取即可
misc59
LSB之两个工具两个工具跑得快跑得快全都解不出来全都解不出来真奇怪真奇怪。
既然两个工具都跑不出来,那应该是把misc57和misc58结合了一下,低位读取+小端存放
。
首先还是stegsolve查看隐写痕迹,然后提取一下LSBFirst
的数据,再进行一下大小端的转换。
这里显然是要把大端转为小端,以头几个字节为例:
0x0a转二进制是00001010(手动补零),反过来就是对应的小端数据:1010000,即0x50
0xd2转二进制是11010010,同样处理得到:1001011,即0x4b
504b,大概是zip了,写脚本:
import binascii
out = ''
f = open('123','rb')
for i in f.read():
if i != 255:
bin_text = bin(i)[2:].zfill(8)
small = hex(eval('0b'+bin_text[::-1]))[2:].zfill(2)
out += small
else:
break
f.close()
f1 = open('out.zip','wb')
f1.write(binascii.a2b_hex(out))
f1.close()
解压拿flag
misc60
提示:LSB之一零二四好人一生平安。
发现RGB Plane的0-4
通道都有隐写痕迹
而且题目已经说了Plane Order = RGB
,那么还需要确定通道的顺序,提示中的一零二四
指出这里的顺序是1-0-2-4
。
from PIL import Image
img = Image.open('misc60.png')
def f(img,axis):
p = img.convert('RGB').getpixel(axis)
out = ''
for i in p:
tmp = bin(i)[2:].zfill(8)
for j in [1,0,2,4]:
out += tmp[7-j]
return out
ans = ''
length = 28
for i in range(length):
ans += f(img,(i,0))
for i in range(len(ans)//8):
print(chr(int(ans[8*i:8*(i+1)],2)),end='')
以上是关于ctfshow-Misc入门 图片篇(50-60)的主要内容,如果未能解决你的问题,请参考以下文章