谢谢重庆工商大学邀请,让我参加比赛,虽然这天满课,但是还是打了个三血出来,嘿嘿
也是在最后用AI搞出来个web题,极限上交
初赛
Misc-[签到]Welcom
在C0ba1t战队的官网,可以看到有个js文件,搜索flag,可以看到这个抓取flag的操作

于是获得路径/api/flag

Misc-两叶障目
两片叶子真的能蒙住你眼睛吗?
只给了个两个叶子的图片,用 010查看器或 Python 检查文件,发现文件中存在两个 JPEG 结束标记 FF D9,说明文件由两张 JPEG 图片拼接而成。

提取出两个图片,可以发现几乎一模一样:
两张图片尺寸完全相同(682×511 RGB),逐像素计算绝对差值,然后等比放大到可视范围。

from PIL import Image
import numpy as np
img1 = np.array(Image.open('leaf1.jpg'))
img2 = np.array(Image.open('leaf2.jpg'))
diff = np.abs(img2.astype(float) - img1.astype(float))
diff_gray = diff.max(axis=2) # 取每个像素的最大通道差
# 此时因为出来的图片很模糊,所以需要放大这种差值,放大到 0-255
diff_scaled = (diff_gray / diff_gray.max() * 255).astype(np.uint8)
Image.fromarray(diff_scaled).save('diff_scaled.png')

官方wp写的另一个方法:

Misc-SGA
还不错的附魔?等等,这个附魔台不太对劲注:请将最终结果按单词以_分离并包上ctbuctf{}提交,全小写

首先SGA翻译下来是附魔台文字
其次,根据这个”以_分离“可以判断出flag绝对是零散的,而且你可以很明确知道他是flag


猜测:Minecraft的附魔铭文编码,第一行开始翻译下来是you have…最后是sga well done it。那就绝对是了

全部对下来就是flag
Misc-Hashcat
给了个一个哈机咪的png,可以发现在文件里存在rar、

发现这个压缩包存在注释

放在随波逐流跑一下

得到打开压缩包的密码(含掩码)
f1agf1ag:xxxx:doyouKKKKNOW

最终得到:
f1agf1ag:4096:doyouKKKKNOW
打开得到:
哈气!禁止随地大小躺!
ctbuctf{ffe45f13-72be-4723-a7ad-00229bfd6b46}
密码-Xor
题目描述
给出一段十六进制密文和关键词 c0ba1t,需要解密得到 flag。
- 关键词:
c0ba1t - 密文:
004400145200054b1b0e442b0f5f14046e17535203504509
分析
看到题目给了一个关键词和一段十六进制密文,首先猜测使用了异或(XOR)加密。
异或加密是对称加密中最简单的一种:将明文与密钥按字节逐位异或得到密文,解密时再用相同密钥与密文异或即可还原明文。
密钥 c0ba1t 长度为 6 字节,密文长度为 24 字节,恰好是 4 倍关系,进一步印证了重复密钥 XOR(即密钥循环使用)的猜测。
解题步骤
1. XOR 解密
将密文转为字节,与重复的密钥 c0ba1t 逐字节异或:
from pwn import xor
ct = bytes.fromhex('004400145200054b1b0e442b0f5f14046e17535203504509')
key = b'c0ba1t'
flag = xor(ct, key)
print(flag.decode())
2. 手动验证(可选)
前 6 字节的异或运算:
| 密文字节 | 密钥字节 | 异或结果 | 明文字符 |
|---|---|---|---|
| 0x00 | 0x63 (c) | 0x63 | c |
| 0x44 | 0x30 (0) | 0x74 | t |
| 0x00 | 0x62 (b) | 0x62 | b |
| 0x14 | 0x61 (a) | 0x75 | u |
| 0x52 | 0x31 (1) | 0x63 | c |
| 0x00 | 0x74 (t) | 0x74 | t |
前 6 字节解密结果为 ctbuct,看起来是合理的 flag 前缀。
也可:

Flag
ctbuctf{you_love_c0ba1t}
Web-签退题
该Url,点击次数设为99999得到flag
Osint
略
线下决赛(Misc)
虽不在线下,但是仍在打
Ercode
题面:

解题过程:
给了个二维码,随波逐流里面一切正常。除了这个分辨率,按道理来说,应该是正方形,但这个是498*499

分析二维码:
分析版本:
一条边的黑白块个数 = 21 + 4 * (version – 1)
37 = 21 + 4 * (version – 1)
version = 5
分析格式信息:
111011111000100
查表:

可知二维码纠错码等级为L,掩码类别为0,此时即可进行去掩模操作得到原始可读取数据的二维码图片
Where is the flag
题面:

解题过程:
两张图片,jpg与png,分别放进随波逐流里面看下文件结构()

压缩包提取出来,用ARCHPR可以爆破:

打开后里面有2个文件。where is the flag和there is no flag.txt.
txt里面零宽字符隐写了个 Where am I?
另一个文件里面是乱码,试试VC容器,但是whereamI?这个密码打不开。
此时想到还有个JPG没有用
用JPG当作密钥,成功挂载,获得flag:ctbuctf{2470f832-7f42-4010-b2f6-df67e97cd743}

小扶同学的台历
题面:

解题过程:
给了个pdf

尾部有一串神秘数字,用-分隔,刚好12组,尝试用这个数字勾勒出日历

用ctbuctf{}包装即可得到:ctbuctf{tel1methedat}
思路优化:
当PDF里不是图片,是文字内容,当pdf放大缩小,里面的文字结构不会变化的时候,要考虑这种文字游戏的方向
谜语人回归
题面:

解题思路:
牢猫(2).png的 alpha 通道只有 0 和 255 两种值,且 alpha=0(透明)的像素有 900720 个,均匀散布在整个画面中。- 观察发现,在 alpha=0 的像素位置,
牢猫(2).png的 RGB 值全为 255(纯白),这些像素本身不携带信息。 - 关键思路:将 alpha 通道作为位置选择器,在 alpha=0 的位置提取
牢猫.png对应像素的信息。 - 结合”绿色”提示,提取
牢猫.png在这些位置的绿色通道值。 - 取每个绿色通道值的 LSB(最低有效位),串联成比特流,转换为字节后即得到一个隐藏的 PNG 文件。
解题过程:
给了两个png,一个全是噪声,一个是正常的。

丢进随波逐流,并无线索
注意到两个图片分辨率都相同,为3834*2160,但是大小差很多,大概差8MB左右
分辨率相同说明要进行基于像素上面的操作
注意到(注意力惊人),牢猫.png在 alpha=0 的像素位置,牢猫(2).png 的 RGB 值全为 255(纯白),这些像素本身不携带信息
结合”绿色”提示,提取 牢猫.png 在这些位置的绿色通道值。取每个绿色通道值的 LSB(最低有效位),串联成比特流,转换为字节后即得到一个隐藏的 PNG 文件。
代码如下
import numpy as np
from PIL import Image
# 读取两张图片
rgb = np.array(Image.open('牢猫.png'))
rgba = np.array(Image.open('牢猫(2).png'))
# 提取通道
alpha = rgba[:, :, 3]
green = rgb[:, :, 1]
# 找到 alpha=0 的位置
mask = (alpha == 0)
hidden_count = np.sum(mask)
if hidden_count == 0:
raise ValueError("没有 alpha=0 的像素,无法提取数据")
# 提取绿色通道值的最低位
green_hidden = green[mask]
lsb_bits = ''.join(str(int(v) & 1) for v in green_hidden)
# 转换为字节
if len(lsb_bits) % 8 != 0:
lsb_bits = lsb_bits[:-(len(lsb_bits) % 8)]
hidden_bytes = bytes(
int(lsb_bits[i:i+8], 2)
for i in range(0, len(lsb_bits), 8)
)
# 定位 PNG 数据
PNG_HEADER = b'\x89PNG\r\n\x1a\n'
start = hidden_bytes.find(PNG_HEADER)
if start == -1:
raise ValueError("未找到 PNG 文件头")
iend = hidden_bytes.find(b'IEND', start)
if iend == -1:
raise ValueError("未找到 IEND 标记")
png_data = hidden_bytes[start:iend + 8]
# 保存并验证
with open('flag.png', 'wb') as f:
f.write(png_data)
img = Image.open('flag.png')
print(f"提取成功: {img.size[0]}x{img.size[1]} {img.mode}")
img.show()
得到flag:
提取出的 384×384 PNG 图片上直接显示 flag。


