[misc]上帝之音 400

0x00 已知条件

给了一个godwave.wav,还有两个提示。

0x01 解法过程

  • Hint1: 你们做音频题都不喜欢看时域图?
    根据这个,用Cooledit看一下时域波形,如下:

image.png

发现波形明显整过,赋值差异很明显,数出周期为64个点。第一次做音频题,看一下writeup,写个脚本把它提取成01序列:
写的过程中值得注意的是:横轴改成smpl,即采样点,每个单位对应一个实心点;纵轴改成norm,表示幅值。这样在编程时,每个点就是横轴对应waveData[i],纵轴对应norm。
另外,判断每周期的值时,本来采用的是计算平均值。后来简化计算改成全部求和,先看了一下低赋值周期最大值不超过0.035,那么64个点最多也就2.24。(不知道题解的这个10是怎么取的,可能是为保险取大点吧)

[Python]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wave
import matplotlib.pyplot as plt
import numpy
import os

path = 'D:\PyCharm\Projects\CTF\Javis OJ\misc\god_wave\\'
wav = wave.open(path+'godwave.wav','rb')

params = wav.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]

strData = wav.readframes(nframes) #读取音频,字符串格式
waveData = numpy.fromstring(strData, dtype=numpy.int16) #上述字符串转int
waveData = waveData*1.0/(max(abs(waveData))) #wave幅值归一化,与Cool edit的norm纵轴数值一致

#将音频转化为01串
string = ''
norm = 0
for i in range(1735680):
    norm = norm+abs(waveData[i])
    if (i+1) % 64 == 0:
        if norm > 10:
            string += '1'
        else:
            string += '0'
        norm = 0

with open('01output.txt','w') as output:
    output.writelines(string)

在输出文件中写了一行01串。

  • Hint2: 在数据传输过程中,我们往往会使用一种自带时钟的编码以减少误码率
    搜索“自带时钟的编码”,说是曼彻斯特编码。写脚本把上面得到的01串做曼彻斯特解码,负电平为1,正电平 为0:
# -*- coding: utf-8 -*-
file_in = open('01output.txt','r')
code = file_in.readline()
file_in.close()
le = len(str(code))
print le
print code

result = ''
count = 0
res = 0
while code != '':
    cp = code[:2]
    if cp != '':
        if cp[0] == '0' and cp[1] == '1':
            res = (res<<1)|0
            count +=1
        if cp[0] == '1' and cp[1] == '0':
            res = (res<<1)|1
            count +=1
        if count == 8:
            result += chr(res)
            count = 0
            res = 0
    else:
        print 'Unexpected cp, exit!' # found '00' or '11', stop the script directly
        break

    code = code[2:]

with open('result.png','wb') as file_out:
    file_out.write(result)

一开始自己写的时候犯蠢,直接每两位出一位写到result里,写出来也打不开。
参(zhao)考(chao)题解用位运算, 逐字节(8位)转成字符写入。打开是个二维码,扫了即可。
也不知道题解怎么知道要存成PNG的……好吧自己试了一下只要是图片格式都能扫,随便选个格式就行。

推荐阅读更多精彩内容