说明

很多出题人可能会把手机或者其他设备打电话的拨号音作为一个题目技能中的考察点。

什么是DTMF?

双音多频的拨号键盘是4×4的矩阵,每一行代表一个低频,每一列代表一个高频。每按一个键就发送一个高频和低频的正弦信号组合,比如’1’相当于697和1209赫兹(Hz)。交换机可以解码这些频率组合并确定所对应的按键。

事实上,我们手机拨打电话的拨号键盘如果没有经过厂商OEM或者刻意调整,一般都是DTMF的拨号音。

例如小米手机,出厂就是DTMF的声音(当然可以设置)

在拨号的时候,你会听到一段有规律且每个按键不会重复的声音,这就是传说中的“拨号音”了。有些大神可以通过人耳进行识别,识别你按下的按键。(不过因为这些音频振幅相似,所以需要刻苦训练)

如何识别他?

如果要辨识DTMF拨号音,我们可以通过工具“DTMF2NUM”进行分辨。

某剧中,有个大神就是通过人耳识别(所以说刻苦训练很重要诶)

工具地址:https://bbs.qsnctf.com/thread-267-1-1.html

分享一个好玩的

当然,寓教于乐。我们下面分享一个好玩的东西:

在某一个列车上,一个老太太把水弄到了旁边年轻人的衣服上。老太太不依不饶的说不是她。随即拿起了电话,拨通了一个号码。但是老太太忽略了乘务人员的记录仪,把老太太拨打电话的场景录了下来。

录完之后,老太太仍然不依不饶的要求赔偿,可结果是老太太的儿子的电话被拔了出来。

不是教大家干坏事的哦!只是想告诉大家如果拨号场景被录制,请一定要求录制方注意信息安全,防止信息泄露。

练习

因为DTMF2num的这个知识点,我出了一道题目放到了青少年CTF平台上。

题目地址:https://www.qsnctf.com/challenges#敢问路在何方-310

当然,我们只需要一个小工具就可以识别wav中的dtmf。

1
dtmf2num.exe xxx.wav

这就是识别结果了。

使用Python识别

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
import scipy.io.wavefile as wav
import scipy.fftpack as fft

# 读取音频文件
fs, data = wav.read('dtmf.wav')
# 计算帧长
frame_length = int(fs * 0.01) # 10ms
# 分帧
frames = []
for i in range(0, len(data), frame_length):
frame = data[i:i+frame_length]
frames.append(frame)
# 识别拨号音
for frame in frames:
# 计算 FFT
fft_result = fft.fft(frame)
# 计算频率分量
frequencies = fft.fftfreq(len(fft_result)) * fs
# 计算振幅分量
amplitudes = abs(fft_result)
# 找到最大振幅对应的频率
max_amplitude_index = amplitudes.argmax()
max_frequency = frequencies[max_amplitude_index]
# 根据频率判断是哪个拨号音
if max_frequency in (697, 770):
print('拨号音:1')
elif max_frequency in (697, 770, 852, 941):
print('拨号音:2')
elif max_frequency in (770, 852):
print('拨号音:3')
elif max_frequency in (770, 852, 941, 1209):
print('拨号音:4')
elif max_frequency in (770, 941):
print('拨号音:5')
elif max_frequency in (852, 941, 1209, 1336):
print('拨号音:6')
elif max_frequency in (941, 1209):
print('拨号音:7')
elif max_frequency in (697, 770,852,941,1209,1336):
print('拨号音:8')
elif max_frequency in (770, 852, 941, 1209, 1336):
print('拨号音:9')
elif max_frequency in (941):
print('拨号音:*')
elif max_frequency in (941, 1336):
print('拨号音:0')
elif max_frequency in (941, 1209, 1336):
print('拨号音:#')