Misc

题目不好评价

puzzle

二血,从早上9点看到下午3点,人已经麻了。第一次在国赛上拿到前三血,记录一下

img

bmp header的两个保留位不是0000,仔细观察和其他碎片的关系,猜测是碎片在原图的位置。

高度的位置比较规整,根据高度分一下碎片,然后脚本拼图

from PIL import Image
import os
import shutil
path = ".\\tmp4"
files = os.listdir(path)

def combine_img(img, w, h, small_img):
width, height = small_img.size
for n_w in range(width):
for n_h in range(height):
tmp = small_img.getpixel((n_w, n_h))
img.putpixel((w + n_w, h + n_h), tmp)

for file in files:
img_path = os.path.join(path, file)
img = Image.open(img_path)
width, height = img.size

with open(img_path, "rb") as f:
data = f.read()[6:10]
w_place = int(data[:2][::-1].hex(), 16) # 小端
h_place = int(data[2:][::-1].hex(), 16)
dirs = os.listdir('.')
tmp_dir = str(h_place) #根据在原图的高度位置分碎片
if tmp_dir not in dirs:
os.mkdir(tmp_dir)
shutil.copyfile(os.path.join(path, file), os.path.join(tmp_dir, str(w_place) + "_" + file))

new_img = Image.new('RGB', (7200, 4000))
dirs = [str(i*100) for i in range(40)]
print(dirs)
for dir in dirs:
print(dir)
p = os.path.join('./', dir)
files = os.listdir(os.path.join('./', dir))

files.sort(key=lambda x: int(x.split('_')[0]))

for file in files:
w_place = int(file.split('_')[0])
h_pace = int(dir)
img = Image.open(os.path.join(p, file))
combine_img(new_img, w_place, h_pace, img)

new_img.save('flag.png')

拼好的图片发现前6行有翻转,仔细看左上角第一个碎片,明显的lsb,得到第一部分flag

flag{f1R5T_part_1s_LSB_sTeG0_

image-20230529110145635

前6行翻转情况转01。根据bmp图片的biHeight,有些是9C FF FF FF,即-100,说明翻转了

image-20230529101406133

BMP默认从左下角开始绘制图像,当图像高度为负数的时候,则会从左上角开始绘制图像。

import os
dirs = [str(i*100) for i in range(6)]

for dir in dirs:
res = ""
p = os.path.join('./', dir)
files = os.listdir(os.path.join('./', dir))
files.sort(key=lambda x: int(x.split('_')[0]))

for file in files:
img_path = os.path.join(p, file)
with open(img_path, "rb") as f:
data = f.read()[0x19]
if(data == 255):
res += "0"
else:
res += "1"
print(res)

'''
001000000010000000100000001000000010000000100000001000000010000000100000
001000000011001001101110011001000101111101110000011000010101001001010100
010111110011000100110101010111110111001001100101010101100110010101010010
010100110110010101011111011000100100110101110000010111110010000000100000
001000000010000000100000001000000010000000100000001000000010111000101101
001011010010111000100000001011100010110100100000001011010010111000101110
'''

得到第二部分flag,并且还给了一个摩斯电码,提示PAD

image-20230529100614329

PAD明显是提示bmp的填充里面藏了数据,bmp的一行数据需要4字节补齐。看了第一张bmp碎片的前两行,发现了填充的数据是ff d8 ff e1,jpg图片,那么脚本提取

from PIL import Image
import os
import shutil
dirs = [str(i*100) for i in range(40)]
r = b''
start = 0x36
for dir in dirs:
p = os.path.join('./', dir)
files = os.listdir(os.path.join('./', dir))
files.sort(key=lambda x: int(x.split('_')[0]))
for file in files:
tmp_r = b''
img_path = os.path.join(p, file)
img = Image.open(img_path)
width, heigth = img.size

with open(img_path, "rb") as f:
data = f.read()

tmp = width * 3
pad = 4 - (tmp % 4)
if pad == 4:
pad = 0
gap = tmp + pad
for i in range(start, len(data), gap):
r += data[i + gap - pad : i + gap]

with open("1.jpg", "wb") as f:
f.write(r)

得到一张jpg,上面是第三部分flag

1

合起来得到总的flag

flag{f1R5T_part_1s_LSB_sTeG0_2nd_paRT_15_reVeRSe_bMp_3rd_parT_1s_paddINGINGING}

pyshell

eval倒是没有限制,但是字符长度限制7

那么可以利用_和+来完成语句拼接

>>'open'      
'open'
>>_
'open'
>>_+'('
'open('
>>_+'"/f'
'open("/f'
>>_+'lag'
'open("/flag'
>>_+'")'
'open("/flag")'
>>_+'.re'
'open("/flag").re'
>>_+'ad'
'open("/flag").read'
>>_+'()'
'open("/flag").read()'
>>_
'open("/flag").read()'
>>eval(_)
'flag{6eec38dd-9845-4b33-b3f4-3083fd422fc5}'

国粹

脑洞题

a.png和k.png长度一样,都是341张麻将牌,猜测一一对应,每张牌代表一个数字,一一对应组合成一个坐标,最后画图

每张牌代表的数字来自 题目.png 的顺序

# 53 x 73
from PIL import Image

def split_img(img, w, h):
tmp_res = []
for n_w in range(53):
for n_h in range(73):
tmp = img.getpixel((w + n_w, h + n_h))
if len(tmp) == 4:
tmp_res.append(tmp[:-1])
elif len(tmp) == 3:
tmp_res.append(tmp)
return tmp_res

img = Image.open("题目.png")
width, height = img.size

pic_index = []
for w in range(0, width, 53):
tmp_res = split_img(img, w, 0)
pic_index.append(tmp_res)

print(len(pic_index))

img_a = Image.open("a.png")
img_k = Image.open("k.png")

width, height = img_a.size
res = []

for w in range(0, width, 53):
tmp = split_img(img_a, w, 0)
tmp1 = split_img(img_k, w, 0)

(x, y) = (pic_index.index(tmp), pic_index.index(tmp1))
res.append((x,y))

print(len(res))

new = Image.new('RGB', (43, 43))

for i in res:
x, y = i
new.putpixel((x, y), (255, 255, 255))

new.save('flag.png')

得到

flag

水平翻转+旋转一下

被加密的生产流量

0x03读取寄存器的word count前几个太大了,明显有问题

tshark -r modbus.pcap -T fields -e modbus.word_cnt > data.txt
image-20230527161948894

流量里可以看到是几个大写字母,提出来base32一下