DASCTF July X CBCTF Misc

问卷题

  • 懂得都懂,不懂也得懂

在这里插入图片描述

red_vs_blue

  • 尝试几次之后发现错误之后重试的话,之前的结果是固定的,即每一轮的结果不会变,所以只需要试错来得到正确的结果即可
from pwn import *
context.log_level = 'debug'

num = 0
p = remote('node4.buuoj.cn',27291)
resultsList = ['r' for res in range(66)]

while 1:
    p.recvuntil('choose one [r] Red Team,[b] Blue Team:\n')
    while 1:
        p.sendline(resultsList[num])
        choice = p.recvline()
        result = p.recvline()
        if choice[-9:] == result[-9:]:
            num += 1
            if num == 66:
                print(p.recvline())
                print(p.recvline())
                print(p.recvline())
                print(p.recvline())
                break
            else:
                p.recvuntil('choose one [r] Red Team,[b] Blue Team:\n')
        else:
            resultsList[num] = 'b'
            num = 0
            p.sendline('y')
            break

在这里插入图片描述

funny_maze

  • 类似于最短路径算法的求解,这里参考官方给出的题解代码
import re
import sys
from pwn import *
context.log_level = 'debug'

sys.setrecursionlimit(10000)

class Point:
    def __init__(self, x, y, _):
        self.x = x
        self.y = y
        self._ = _
        self.sum = 0
        self.next = [x, x, x, x]
        self.next[0] = -1, -1
        self.next[1] = -1, -1
        self.next[2] = -1, -1
        self.next[3] = -1, -1
        self.next_list = [-1, -1, -1, -1]
    # 记录相邻点的相关数据
    def join(self, x, y, s, e, w):
        if self._ == s or self._ == e or self._ == w:
            if x == self.x + 1 and y == self.y:
                self.next_list[self.sum] = 0
                self.next[0] = x, y
                self.sum += 1
                return 1
            if x == self.x - 1 and y == self.y:
                self.next_list[self.sum] = 1
                self.next[1] = x, y
                self.sum += 1
                return 1
            if x == self.x and y == self.y - 1:
                self.next_list[self.sum] = 2
                self.next[2] = x, y
                self.sum += 1
                return 1
            if x == self.x and y == self.y + 1:
                self.next_list[self.sum] = 3
                self.next[3] = x, y
                self.sum += 1
                return 1
        return 0

def load(path, start, end, way):
    x = 0
    y = 0
    startx = -1
    starty = -1
    endx = -1
    endy = -1
    mapy = []
    for lines in path:
        mapx = []
        for c in lines:
            mapx.append(Point(x, y, c))
            if c == start or c == end or c == way:
                if c == start:
                    startx = x
                    starty = y
                if c == end:
                    endx = x
                    endy = y
                if x > 0:
                    if mapx[x - 1].join(x, y, start, end, way) == 1:
                        mapx[x].join(x - 1, y, start, end, way)
                if y > 0:
                    if mapy[y - 1][x].join(x, y, start, end, way) == 1:
                        mapx[x].join(x, y - 1, start, end, way)
            x += 1
        mapy.append(mapx)
        x = 0
        y += 1
    return mapy, startx, starty, endx, endy

def re_find_the_way(x, y, MAP, map1, map2, end):
    map1[y][x] = 1
    if map2[y][x] == '#':
        map2[y][x] = '.'
    if MAP[y][x]._ == end:
        lengh = 0
        for m1 in map1:
            for m2 in m1:
                if m2 == 1:
                    lengh += 1
        return map1, map2, lengh, 1
    for i in range(MAP[y][x].sum):
        xx, yy = MAP[y][x].next[MAP[y][x].next_list[i]]
        if map1[yy][xx] == 0:
            r1, r2, r3, r4 = re_find_the_way(xx, yy, MAP, map1, map2, end)
            if r4 == 1:
                return r1, r2, r3, r4
            else:
                map1[yy][xx] = 0
                map2[yy][xx] = '#'
    return map1, map2, 0, 0

def find_the_way(path, start, end, way):
    MAP, startx, starty, endx, endy = load(path, start, end, way)
    map1 = []
    map2 = []
    for y in MAP:
        map1_ = []
        map2_ = []
        for x in y:
            map1_.append(0)
            map2_.append('#')
        map1.append(map1_)
        map2.append(map2_)
    map2[starty][startx] = start
    map2[endy][endx] = end
    map1, map2, length, r4 = re_find_the_way(startx, starty, MAP, map1, map2, end)
    return length

if __name__ == '__main__':
    if len(sys.argv) != 4:
        print("Usage: python exp.py ip port flag")
        sys.exit()
    p = remote(sys.argv[1], int(sys.argv[2]))
    FLAG = sys.argv[3]
    list1 = []
    while 1:
        a = p.recvuntil('Introduction to this game\n')
        p.sendline('1')
        while 1:
            try:
                p.recvuntil('#')
            except:
                while 1:
                    a = p.recvline().decode().strip('\n')
                    print(a)
                    if 'flag{' in a:
                        flag = re.findall('flag{(.*?)}', a)
                        if flag[0] == FLAG:
                            print('Pass!')
                        else:
                            print('AssertionError!')
                        sys.exit()
            while 1:
                a = p.recvline().decode().strip('\n')
                print(a)
                if a != '#' and a != 'S':
                    pass
                if a != 'Please enter your answer:':
                    list1.append(a)
                    print(list1)
                    continue
                else:
                    length = find_the_way(list1, 'S', 'E', ' ')
                    p.sendline(str(length))
                    print(length)
                    break

在这里插入图片描述

ezSteganography

  • 的确是有手就行的题目,手撕论文的那种
  • 题目名字已经提示是图片隐写了,由于是 png 格式的图片,用 zsteg 查看一下发现一张 png 图片,将其分离出来,得到前半部分 Flag,并且提示 QIM 算法对后续解题是有帮助的,给出了 step 的数值为 20

在这里插入图片描述
请添加图片描述

非预期解

  • 提取出 g0g1 异或也可以得到后半部分 Flag,其原因为步⻓为 20,其 1/45,也就是⽔印会导致奇偶像素不同,所以可以异或出来

在这里插入图片描述

预期解

  • 参考 QIM 算法实现提取的原理
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def extract(delta, y):
    out = []
    for i in (delta / 2 - y % delta):
        if i > 0:
            out.append(1)
        else:
            out.append(0)
    out = np.array(out)
    return out

if __name__ == '__main__':
    imagePath = r'C:\Users\95235\Downloads\ezSteganography-flag.png'
    p = np.array(Image.open(imagePath))
    R, G, B = p[:,:,0], p[:,:,1], p[:,:,2]
    G = G.ravel()
    te_out = extract(20, G)
    plt.imshow(np.array(te_out).reshape(1440,2560))
    plt.show()

在这里插入图片描述

Just a GIF

  • 将 GIF 逐帧分开后将相同的图片分成一组,可以分为 11 个系列,然后系列中的图片与该系列第一张图片比较,新建一张 83x83 的空白图,把所有存在像素值不同的位置标记为黑色,即可得到隐藏的 11 张图片中的 1 张,剩下的以此类推即可
import os
from PIL import Image
from tqdm import tqdm

img = Image.open(r'C:\Users\95235\Downloads\gif\Just_a_GIF.gif')
os.mkdir(r'C:\Users\95235\Downloads\gif\png')
for i in range(img.n_frames):
    img.seek(i)
    new = Image.new('RGB', img.size)
    new.paste(img)
    new.save(r'C:\Users\95235\Downloads\gif\png\\' + str(i) + '.png')

os.mkdir(r'C:\Users\95235\Downloads\gif\flag')
path_1 = r'C:\Users\95235\Downloads\gif\flag\\'
path_2 = r'C:\Users\95235\Downloads\gif\png\\'

for i in tqdm(range(11)):
    img = Image.open(path_2 + str(i) + '.png')
    img_1 = Image.new('RGB', (83,83), (255,255,255))
    for h in range(40):
        im = Image.open(path_2 + str((h+1)*11+i) + '.png')
        width, height = img.size
        for j in range(0, width):
            for k in range(0, height):
                tmp = img.getpixel((j,k))
                tmp_1 = im.getpixel((j,k))
                if tmp != tmp_1:
                    img_1.putpixel((j,k), (0,0,0))
    img_1.save(path_1 + str(i+1) + '.png')

在这里插入图片描述

  • 将得到的九张带有二维码碎片的图片按照另两张图片标明的排布拼起来
from PIL import Image

a = [7, 1, 6, 9, 3, 4, 5, 2, 8]
f = Image.new("RGB", (83 * 3, 83 * 3))
for i in range(0, 3):
    for j in range(0, 3):
        path = r"C:\Users\95235\Downloads\gif\flag\\" + str(a[i + j * 3]) + ".png"
        x = Image.open(path)
        f.paste(x, (i * 83, j * 83))
f.save(r"C:\Users\95235\Downloads\gif\flag\flag.png")

在这里插入图片描述

  • 用中国编码扫码就可以拿到 Flag 了,码制为 DATA_MATRIX

Nuclear wastewater

  • 观察到二维码的颜色有点不同于寻常,提取出来看看,由于每个块都是 10*10 这里我们只提取每个块中第一个像素
from PIL import Image

img = Image.open(r"C:\Users\95235\Downloads\Nuclear_wastewater\key.png")
for y in range(img.size[1]):
	list_pix = []
		for x in range(img.size[0]):
			if (y % 10 == 0 and x % 10 == 0):
				list_pix.append(img.getpixel((x,y)))
		if list_pix != []:
			print(list_pix)

在这里插入图片描述

  • 提取出来之后发现除了白色只有 RGB 中一个有值这一规律外并没有什么其他规律,将 RGB 分组也没有发现什么东西,尝试将颜色值转换成 ASCII 码后得到字符串 (不可打印字符不包括在内):'Ys>UEJht#? ppeEFtstR#~:hi~tR:@s@YRteK#e@KsR&E&:eR:Eht/#iKtteYKhYKYhhhihhKtC2tt:HVEesY&#@Rj! seRi:eitEtKsetKtEE:hh#h#eYKYihhYK(Kt@iSY$KY/@pRsEetsip:~h@eeEs!E&&::EsEEei#/iYe# /ieKKt//iKYhh'
  • 发现字符串内有很多重复的字符,统计词频后得到:Counter({'t': 18, 'h': 17, 'e': 16, 'K': 15, 'E': 14, 'Y': 13, 'i': 12, 's': 11, ':': 10, '#': 9, 'R': 8, '@': 7, '/': 6, '&': 5, 'p': 4, '~': 3, '!': 2, '>': 1, 'U': 1, 'J': 1, '?': 1, 'F': 1, 'C': 1, '2': 1, 'H': 1, 'V': 1, 'j': 1, '(': 1, 'S': 1, '$': 1})
from PIL import Image

pic = Image.open(r'C:\Users\95235\Downloads\Nuclear_wastewater\Nuclear wastewater.png')
w, h = pic.size
list_1 = []

for y in range(0, h, 10):
    for x in range(0, w, 10):
        pixel = pic.getpixel((x, y))
        if pixel == (255, 255, 255):
            continue
        r, g, b = pixel
        list_1.extend([r, g, b])

dict_1 = {}
for i in list_1:
    dict_1[i] = dict_1.get(i, 0) + 1

result = sorted(dict_1.items(), key=lambda x: x[1], reverse=True)
for s in result:
    print(chr(s[0]), end="")
  • 将出现次数为 1 的丢弃,拿到压缩包的密码:#R@/&p~!
  • 查看 flag.txt,发现存在零宽字符隐写,在线解密

在这里插入图片描述

在这里插入图片描述

发现提示,搜索关键词 “Citrix CTX1” 发现是一种加密方式,继续在线解密,两次解密即可拿到 Flag

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值