考察知识点:音频分析,未知算法推测

1.下载附件,发现是个wav文件,于是我们拖进AU进行频谱分析

QQ图片20220228130745-1536x929

通过放大观察到频谱里有间隔的字符,组成字符串可得:

AnEWmuLTiPLyis_etimes_willbEcomE_B

把字符串按照我们能读懂的英文拆开:a new multiply is “e” times “_” will become b
翻译成中文就是有一种乘法是‘e’乘以‘_(下划线)’将会等于b

2.接着我们用音频隐写解密工具Silenteye,对音频进行解密:

得到一串base64编码的字符串:

MjA3IDM1OSAyMjAgMjI0IDM1MiAzMTUgMzU5IDM3NCAyOTAgMzEwIDI3NyA1MDcgMzkxIDUxMyA0MjMgMzkyIDUwOCAzODMgNDQwIDMyMiA0MjAgNDI3IDUwMyA0NjAgMjk1IDMxOCAyNDUgMzAyIDQwNyA0MTQgNDEwIDEzMCAzNjkgMzE3

解码后得到:
207 359 220 224 352 315 359 374 290 310 277 507 391 513 423 392 508 383 440 322 420 427 503 460 295 318 245 302 407 414 410 130 369 317

我们可以发现三位数的个数与英文字符串都是34个,可以猜测英文字符是否与三位数一一对应

3.正当我们一筹莫展的时候,官方给出了两个Hint:

(1)新的乘法指得是ASCII码相乘

(2)下划线的ASCII码是95

4.结合上面的四个线索,我们开始推理:

首先,我们先根据那串英文的意思试试**’e’*‘_’**等于多少:

e=ord('e')
u=ord('_')
print(e*u)

结果为9595,发现并没有什么用。于是我们把目光放到了那堆三位数上面,于是我们开始猜测9595与那些数字有啥关系:

num = ['207',' 359',' 220',' 224 ','352 ','315 ','359 ',
'374',' 290 ','310',' 277',' 507 ','391 ','513 ',
'423',' 392 ','508 ','383',' 440 ','322',' 420',
'427',' 503 ','460 ','295',' 318 ','245',' 302 ',
'407',' 414',' 410',' 130 ','369 ','317']
e=ord('e')
u=ord('_')
for i in range(len(num)):
print(e*u/int(num[i]))

输出的结果为:

46.35265700483092
26.72701949860724
43.61363636363637
42.83482142857143
27.258522727272727
30.46031746031746
26.72701949860724
25.655080213903744
33.08620689655172
30.951612903225808
34.63898916967509
18.925049309664693
24.539641943734015
18.703703703703702
22.68321513002364
24.477040816326532
18.887795275590552
25.052219321148826
21.806818181818183
29.79813664596273
22.845238095238095
22.470725995316158
19.07554671968191
20.858695652173914
32.52542372881356
30.17295597484277
39.16326530612245
31.771523178807946
23.574938574938574
23.17632850241546
23.402439024390244
73.8076923076923
26.00271002710027
30.26813880126183

我们可以观察到倒数第二行的26.00271002710027更接近整数26,此时对应的三位数是369。很契合”will“这个单词—”约等于“

故我们可以列出近似式:(10195)~(26369) PS:ascii(‘e’)=101 ascii(‘_’)=95

我们来看看误差为多少:

e=ord('e')
u=ord('_')
print(e*u-369*26)

输出的结果为1 好家伙是个整数 那可以大概推算出加密的算法了:

(26*对应的三位数+1)/对应的字符的ASCII码=明文的ASCII码

对于这个等式我们暂时保持怀疑的态度

5.我们知道本次比赛的Flag格式为:SUSCTF{} 我们可以推测出’S’被加密为了‘A’

PS:ascii(‘A’)=65 ascii(‘S’)=83

我们把这个猜测带入上面的算法里进行验证:

print((26*207+1)/65)

输出结果为:82.81538461538462

我们发现计算的结果并不是等于S的ASCII码,存在误差。这时候我们又想到了will约等于,我们推测算法会把计算出的结果进行四舍五入值,即82.81538461538462会变成83。那会很好奇为什么第一个式子的误差为整数,即计算结果等于答案,原因是因为我们把26.00271002710027进行四舍五入为26。于是我们可以列出最终的等式:

四舍五入{(26\对应的三位数+1)/(对应的字符的ASCII码)}=明文的ASCII码

最终的代码为:

num = ['207',' 359',' 220',' 224 ','352 ','315 ','359 ',
'374',' 290 ','310',' 277',' 507 ','391 ','513 ',
'423',' 392 ','508 ','383',' 440 ','322',' 420',
'427',' 503 ','460 ','295',' 318 ','245',' 302 ',
'407',' 414',' 410',' 130 ','369 ','317']

a = 'AnEWmuLTiPLyis_etimes_wiLLbEcomE_B'


flag = ''

for i in range(len(num)):
aa = ord(a[i])
n = int(num[i])
flag = flag + chr(round((n * 26 + 1)/aa))

print(flag)

Flag:SUSCTF{tHe_matter_iS_unremArkab1e}