折腾好几个小时只做出了一道 Misc 题(虽然拿了一血),但总归还是太菜了。

题目

题面「听听这是什么」,题给文件有 hint.png嘘.wav 以及 this is our secret.bmp

题解

先看 hint.png,这不是常见的 QR Code,在「二维码」的 Wikipedia 页面中可以找到目前常用的二维码,其中可以靠特征识别出这个是「汉信码」

使用在线工具可以识别这个二维码,得到:

1
2
length:189
0urS3cret

这已经很明示了,this is our secret.bmp 是 OurSecret 软件生成的加密文件,使用 0urS3cret 作为密码在软件中解密后得到 haha.txt,内容如下:

1
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_}{-?!

看起来这是个字符表。最后只剩下一个 WAV 文件了,直接先整个频谱图看看:

Spectrogram.webp

不难看出主要出场的只有 10 个频率,直接进行代码分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import librosa
import numpy as np

# 读取音频文件
audio_file = '嘘.wav'
y, sr = librosa.load(audio_file)

# 设置参数
frame_length = int(sr * 0.1) # 0.1 秒的帧长度
hop_length = int(sr * 0.01) # 0.01 秒的帧间隔

# 计算 STFT
D = librosa.amplitude_to_db(
np.abs(librosa.stft(y, n_fft=frame_length, hop_length=hop_length)), ref=np.max)

# 找到每个时间窗口内的最高响度的频率
max_freqs = np.argmax(D, axis=0)
freqs = librosa.fft_frequencies(sr=sr, n_fft=frame_length)

# 输出每个时间窗口的时间和对应的最高频率
for i, frame in enumerate(max_freqs):
time_in_seconds = i * hop_length / sr
freq_at_max_amplitude = freqs[frame]
print(f"Time: {time_in_seconds:.1f}s, Frequency: {freq_at_max_amplitude:.2f}Hz")

分析输出,基本上可以看出每 0.1s 维持一个频率。盲猜每 0.2s 表示一个字符(10 个频率从低到高 0~9,两位数直接在字符表中下标找字符),稍微修改下结尾的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
result = []
for i, frame in enumerate(max_freqs):
time_in_seconds = i * hop_length / sr
if int(time_in_seconds*100) % 10 == 5:
freq_at_max_amplitude = freqs[frame]
pos = int(freq_at_max_amplitude/100)-8
result.append(pos)

raw = ""
for i, pos in enumerate(result):
raw += str(pos)
if i % 2 == 1:
raw += " "
ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_}{-?!"
for i in raw.strip().split():
print(ALPHABET[int(i)], end="")

得到结果:

1
jadjhadjkadkahkdhkawhdkftwduIGCSACVJBWKDBQQWQUFVCBIQWLKDQHUhuigygslkcnsebajuodilkasnvaolwfnckubagvsoiLHKCnkdbjviuseiflhawnkvbjkdvleskafnkawpofopafoDASCTF{Wh1stling_t0_Convey_informat1on!!!}

其中有 Flag:DASCTF{Wh1stling_t0_Convey_informat1on!!!}