2025 问号CTF Week1
2026-08-22 20:05:38

[Week1] 《关于我穿越到CTF的异世界这档事:序》

The key has never been far away; itàlies peacefully within the text itself.

密钥从未远离;它就静静地躺在文本本身之中

Base隐写

搜了一下这块是Base隐写 是通过Base64编码过程的特性进行的隐写方法 也叫Base64隐写

Base64字符表是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

Base64的编码过程中,会补足位数到6的倍数,而最后几个bit可能是补位的,不真正代表原始数据,比如A的ASCII码是65转换成二进制是01000001(8位)要变成6的倍数 需要凑成24位(3字节)所以需要补两个8位 也就是两个00000000

得到01000001 0000000 000000000拆解成4组6位010000 010000 000000 000000

对应索引是16 16 = =查表得到Q Q = =

隐写的核心在于 第二个Q的后四位0000实际上是补足之后得到的 并不影响转换

Base64隐写通过那些未使用的低位来嵌入秘密信息

把原来的010000 010000 000000 000000

改成010000 01xxxx 000000 000000

010000011111就是十进制1631对应Base64Q``R``Sf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import base64

def get_diff(s1, s2):
"""计算两个 Base64 字符串在对应位置上的索引差值(仅第一个不同位置)"""
base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for i in range(len(s2)):
if s1[i] != s2[i]:
return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
return 0

def b64_stego_decode():
"""
从文件 alphabet.txt 中读取每行 Base64 隐写字符串,
提取隐藏的二进制数据,并还原为 flag。
"""
file = open("alphabet.txt", "rb")
x = '' # 用于存储提取出的二进制字符串
lines = file.readlines()
file.close()

for line in lines:
# 去除换行符,得到原始隐写后的 Base64 字符串
stego = line.decode('utf-8').strip()
if not stego:
continue

# 将其解码为原始字节,再重新编码为“标准”Base64(无隐写)
real_bytes = base64.b64decode(stego)
realtext = base64.b64encode(real_bytes).decode('utf-8')

# 计算隐写串与标准串的差异
diff = get_diff(stego, realtext)
n = stego.count('=') # 统计填充符数量

# 根据填充数量决定隐藏了多少位(每个 '=' 对应 2 位)
if diff:
# 将 diff 转为二进制,补零到 n*2 位
x += bin(diff)[2:].zfill(n * 2)
else:
x += '0' * (n * 2)

# 将二进制字符串按每 8 位转为 ASCII 字符
flag = ''
i = 0
while i < len(x):
byte_str = x[i:i+8]
if len(byte_str) == 8:
char_code = int(byte_str, 2)
if char_code != 0: # 忽略空字符(可选)
flag += chr(char_code)
i += 8

print(flag)

if __name__ == '__main__':
b64_stego_decode()

字母表是?CTFmisc

根据第二个txt的名字了解到用Base8

Base8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def base8_custom_decode(cipher_text, alphabet):
# 创建字符到索引的映射(每个字符对应一个0-7的数字)
mapping = {ch: i for i, ch in enumerate(alphabet)}

# 将密文中的每个字符转换为3位二进制字符串(因为是八进制,0-7 -> 3 bits)
bits = ''.join(f"{mapping[ch]:03b}" for ch in cipher_text if ch in mapping)

# 每8位组成一个字节,忽略不足8位的末尾部分
bytes_list = [
int(bits[i:i+8], 2)
for i in range(0, len(bits), 8)
if len(bits[i:i+8]) == 8
]

# 将字节列表转为 bytes 并尝试解码为字符串(忽略无法解码的部分)
return bytes(bytes_list).decode(errors="ignore")


if __name__ == "__main__":
alphabet = input("请输入字母表:\n")
cipher = input("请输入密文:\n")
result = base8_custom_decode(cipher, alphabet)
print("解密结果:", result)

ZmxhZ3tUaDNfUHIxbmMxcGwzXzBmX0Jhc2VfMXNfUzBfRXp6fQ==

flag{Th3_Pr1nc1pl3_0f_Base_1s_S0_Ezz}

[Week1] 俱乐部之旅(1) - 邀请函

要密码 提示掩码爆破c5im????

c5im8467

打开以后啥也没有 CTRL+A却有一堆东西

根据这段提示 你大概就知道这是要把.docx改成.zip格式就行了嗯嗯

从文档加密看属性 看到提示用cyberchef

cyberchef 按照提示做7位二进制就可以了

但是这好像只是flag的一半

根据那个提示 直接把.docx的后缀名换成.zip即可 然后解压缩包

header1.xml重要的内容就应该存在备注中 那我们看备注那个 发现一段Hex

两半flag合上

flag{W0rd_5t3g_is_1z&Welc0me_t0_th3_c5im_C1ub}

[Week1] 布豪有黑客(一)

题干提到http 作为筛选器

password是?CTF2025

pk头说明是zip文件

显示为原始数据

flag{Wireshark_1s_4wes0m3}

[Week1] 文化木的侦探委托(一)

用之前存下来的crc爆破长宽脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import binascii
import struct

crcbp = open("strange.png", "rb").read() #打开图片
crc32frombp = int(crcbp[29:33].hex(),16) #读取图片中的CRC校验值
print(crc32frombp)

for i in range(4000): #宽度1-4000进行枚举
for j in range(4000): #高度1-4000进行枚举
data = crcbp[12:16] + \
struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]
crc32 = binascii.crc32(data) & 0xffffffff
# print(crc32)
if(crc32 == crc32frombp): #计算当图片大小为i:j时的CRC校验值,与图片中的CRC比较,当相同,则图片大小已经确定
print(i, j)
print('hex:', hex(i), hex(j))
exit(0)

flag{Please_Find_ME}

[Week1] 维吉尼亚朋友的来信

你用眼睛仔细去听 去看频谱图

deepsound 对应题目说信件从深处的声音传来

是不是该有个工具叫deepsound 去搜一下

http://www.hiencode.com/vigenere.html 维吉尼亚密码在线网址

flag{funny_letter_to_you}

上一页
2026-08-22 20:05:38
下一页