第七届浙江省大学生网络与信息安全竞赛决赛 Misc方向全解
第七届浙江省大学生网络与信息安全竞赛决赛 Misc方向全解
FinalSign
给了一个txt,全选可以很明显看到存在空白字符
考虑SNOW隐写(snow特征,有大量的20
,09
)
SNOW.EXE -C FinalSign.txt
得到xorkey:helloworld
,那么很明显2c243f2f3b3114345d0a0909333f06100143023b2c55020912
就是密文
法一:
利用pwntools的xor函数
from pwn import xor
from Crypto.Util.number import *
key = b'helloworld'
c=0x2c243f2f3b3114345d0a0909333f06100143023b2c55020912
print(xor(long_to_bytes(c),key))
法二:
用CyberChef也可以
法三:
a=bytes.fromhex('2c243f2f3b3114345d0a0909333f06100143023b2c55020912')
key=b'helloworld'
e=[]
for i in range(0,len(a)):
e.append(a[i]^key[i%len(key)])
print(bytes(e))
#b'DASCTF{F1nal_Sign1n_D0ne}'
非黑即白
很明显是逆序的GIF
with open('非黑即白','rb') as f:
with open('heibai.gif','wb') as g:
g.write(f.read()[::-1])
GIF常见考点
- 拆分图片
- GIF时间间隔隐写
这题刚好都考察了
identify -format "%s %T \n" heibai.gif | head -n 20
可以看到前15张图的时间间隔与后面的完全不同,转字符
a=[118,106,69,74,48,98,83,117,77,79,86,65,90,103,101]
print(bytes(a))
#b'vjEJ0bSuMOVAZge'
即为压缩包密码
法一:
拆分工具有很多,都可以用
将黑色的图转为0
,其他的转为1
,得到一个加密的zip
from PIL import Image
flag = ''
for i in range(0, 1536):
img = Image.open(str(i)+'.png')
pixel = img.getpixel((0, 0))
# 计算亮度
brightness = 0.299 * pixel[0] + 0.587 * pixel[1] + 0.114 * pixel[2]
# 根据亮度与阈值比较,使用公式 0.299 * R + 0.587 * G + 0.114 * B 计算亮度,这个公式是基于人眼对不同颜色的敏感度
if brightness >= 128:
flag += '1'
else:
flag += '0'
print(flag)
2进制转16进制,504b0304是压缩包的特征
存为文件
利用刚才的密码解压得到flag
DASCTF{H3r3_1s_C0L0rful_W0rld}
法二:
逐帧处理,不用拆分gif
from PIL import Image
a=Image.open("1.gif")
n=0
data=""
e=[]
while True:
try:
a.seek(n) #逐帧处理
d=a.copy().convert('1').getdata() #转换为黑白图像(模式 '1'),然后获取其像素数据。
if (d[0]==0):
data+='0'
else:
data+='1'
except:
break;
if (len(data)==8):
e.append(int(data,2))
data=''
n+=1
f=open("data.zip",'wb')
f.write(bytes(e))
f.close()
注:黑白图片并不是纯的rgb(0,0,0)和rgb(255,255,255),存在(1,1,1)等情况,所以要设置阈值,不然会丢失精度影响输出结果
天命人
按照黑猴的章节名排序
火照黑云
风起黄昏
夜生白露
曲度紫鸳
日落红尘
未竟
没玩过没关系,观察字节即可
发现按照顺序取一个字节是50 4b 03 04 00 0a
f1 = open('火照黑云', 'rb').read()
f2 = open('风起黄昏', 'rb').read()
f3 = open('夜生白露', 'rb').read()
f4 = open('曲度紫鸳', 'rb').read()
f5 = open('日落红尘', 'rb').read()
f6 = open('未竟', 'rb').read()
with open('output.zip', 'wb') as fout:
min_length = min(len(f1), len(f2), len(f3), len(f4), len(f5), len(f6))
# 按字节逐个写入每个文件的数据
for i in range(min_length):
# 逐字节读取每个文件并转换为16进制
hex_bytes = bytes([f1[i], f2[i], f3[i], f4[i], f5[i], f6[i]])
# 将这些字节写入输出文件
fout.write(hex_bytes)
拼接得到zip
4bytes的crc32碰撞,用曾哥的工具就行
python CRC32-Tools.py -4 根器.zip
+-------------对输出的CRC值进行碰撞-----------------+
[Success] 0x76899d01: C0M3
[Success] 0x8e036aa6: _4ND
[Success] 0x881d716a: _Get
[Success] 0x7f3d8e75: _S1X
[Success] 0x248d3c69: _R00
[Success] 0xcb27d2bd: TS!!
+-----------------CRC碰撞结束!!!-----------------+
读取成功,导出CRC列表为:[0x76899d01, 0x8e036aa6, 0x881d716a, 0x7f3d8e75, 0x248d3c69, 0xcb27d2bd]
CRC碰撞成功,结果为: C0M3_4ND_Get_S1X_R00TS!!
利用密码解开未竟.zip
提取金箍棒.png
上的像素点,这里直接用B神的脚本(不能出现中文路径或文件名,在windows下运行)
python3 Get_Pixels.py -f 1.png -p 5x5+1915x1075 -n 10x10
在ps中按F8即可查看坐标
import os
import re
import cv2
import argparse
import itertools
import numpy as np
parser = argparse.ArgumentParser()
parser.add_argument('-f', type=str, default=None, required=True,
help='输入文件名称')
parser.add_argument('-p', type=str, default=None, required=True,
help='输入左上顶点和右下顶点坐标 (如:-p 220x344+3520x2150)')
parser.add_argument('-n', type=str, default=None, required=True,
help='输入宽度间隔和高度间隔 (如:-n 44x86)')
parser.add_argument('-size', type=str, default='1x1', required=False,
help='输入截取图像的大小 (如:-size 7x7)')
parser.add_argument('-resize', type=int, default=1, required=False,
help='输入截取图像放大倍数 (如:-resize 1)')
args = parser.parse_args()
if __name__ == '__main__':
if re.search(r"^\d{1,}x\d{1,}\+\d{1,}x\d{1,}$", args.p) and re.search(r"^\d{1,}x\d{1,}$", args.n) and re.search(r"^\d{1,}x\d{1,}$", args.size):
x1, y1 = map(lambda x: int(x), args.p.split("+")[0].split("x"))
x2, y2 = map(lambda x: int(x), args.p.split("+")[1].split("x"))
width, height = map(lambda x: int(x), args.n.split("x"))
width_size, height_size = map(lambda x: int(x), args.size.split("x"))
img_path = os.path.abspath(args.f)
file_name = img_path.split("\\")[-1]
img = cv2.imread(img_path, cv2.IMREAD_COLOR)
row, col = img.shape[:2]
r, c = len(range(y1, y2 + 1, height)), len(range(x1, x2 + 1, width))
new_img = np.zeros(shape=(r * height_size * args.resize, c * width_size * args.resize, 3))
for y, x in itertools.product(range(r), range(c)):
for y_size in range(height_size):
for x_size in range(width_size):
# new_img[y * height_size + y_size, x * width_size + x_size] = img[y1 + y * height + y_size, x1 + x * width + x_size]
pt1 = ((x * width_size + x_size) * args.resize, (y * height_size + y_size) * args.resize)
pt2 = ((x * width_size + x_size) * args.resize + args.resize, (y * height_size + y_size) * args.resize + args.resize)
color = img[y1 + y * height + y_size, x1 + x * width + x_size].tolist()
cv2.rectangle(new_img, pt1=pt1, pt2=pt2, color=color, thickness=-1)
cv2.imwrite(f"_{file_name}", new_img)
print("已保存到运行目录中...")
else:
print("参数-p或参数-n或参数-size, 输入错误!")
或者
from PIL import Image
a = Image.open("金箍棒.png")
x, y = 5, 5
x_, y_ = 0, 0
w, h = a.size
b = Image.new(a.mode, (w // 10, h // 10))
for x in range(5, w, 10):
for y in range(5, h, 10):
print(x, y, x_, y_)
b.putpixel((x_, y_), a.getpixel((x, y)))
y_ += 1
x_ += 1
y_ = 0
b.save('1.png')
都能得到密码:jinggubang
也有非预期解法,其实缩放一下能看到有字母,翻翻通道多对比一下是能看出来的
还有一个紧箍咒,一眼加密磁盘
金箍棒.png是密钥文件,正常挂载后得到flag
0 条评论
可输入 255 字