地理聊天,有害机器人和隐秘术:丰富有关电报的知识


您对电报中的电报了解多少?并且可以在VideoNote中区分隐写术吗?我们分析了NeoQUEST-2020这个非常艰巨的任务,它引起了我们最多的疑问和惊叹!剧透:是的,这里还会有一些加密货币:)

NeoQUEST-2020图例中,我们找到了指向 Instagram上旅行机器人的个人资料的链接没有什么不寻常的,对吧?因此,我们也做出了这样的决定,但是我们仍然需要解决问题,因此我们仔细考虑配置文件中的所有图片,并至少寻找一些线索。稍微思考一下贝加尔湖的一幅美丽的图画,我们就意识到线索在最后一篇文章中:


多亏了这张图片,我们知道我们需要以某种方式将贝加尔湖(萨满摇滚乐队)和电报(T可以加入我的...-这没有任何提醒吗?)。最初,我们决定不给参与者直接的地理聊天提示(就是这样!),他们中的许多人使用具有更改地理位置的仿真器或移动设备成功地完成了任务。Shamanim我们在Shamanka岩石区域设置坐标(53.20074,107.349426)(可以通过眼睛看到),并为最困难的事情做好准备-等待。电报奇怪地与地理位置一起使用,并且拉起了相关的联系人和聊天一个小时。为了我们的勤奋和耐心,我们获得了丰厚的回报-所需的聊天出现在“联系人”部分->查找附近的人->附近的群组。


瞧,我们在做生意!


僵尸程序通过一个文件形式的内容来解决我们的任务,该文件的字节数中包含未知内容,我们可以在其中读取“解密我”和“启示录中没有人”这两行。

我们理解第一行没有任何问题,但是第二行是什么意思呢?..在这里,参与者分为两个阵营:一些人以邮寄的方式写信给我们,因为他们陷入了死胡同,而另一些人则仔细地看了一下“ Apocalypse Spares Nobody”这一短语,并意识到了这一点。 ?对!良好的旧ASN.1格式此处我们已经写过有关如何解析它的信息)。


让我们做对。里面有2个结构。在其中一个中,我们找到了一组标记为“解密我”的字节,从中我们假定这是密文。在第二个结构中,我们看到两个数字。这不太可能是参与者与密文一起慷慨提供的密钥,这很可能意味着密码。我们正在处理一个公共密钥。收集的所有信息使我们得出一个显而易见的结论-为什么不尝试RSA

因此,我们有一个模块和一个打开指示器,顺便说一句,它很大。经过对RSA抽搐研究后,我们得出结论,封闭指标很小,这意味着什么?答对了!我们绝对可以扮演坏人,并利用维纳的进攻

即使对于不喜欢密码学的人来说,我们也可以仔细考虑-您可以使用现成的攻击版本,例如this

然后,我们得到一个闭合数字的值d=40553818206320299896275948250950248823966726834704013657854904761789429403771并解密密文:key=nq2020faAeFeGUCBjYf7UDrH9FapFCdFPa4u;pass=passCxws3jzYhp0HD5Fy84

我们在工作的第一部分获得了密钥“ nq2020faAeFeGUCBjYf7UDrH9FapFCdFPa4u”和密码“ passCxws3jzYhp0HD5Fy84”,您需要将其提供给机器人代表。可以在聊天参与者中以@neoquestbot的名称找到它。

收到第一把钥匙后,我们就变得积极起来,我们没有立即意识到该机器人在通信方面很挑剔,并且一直说它没有看到对话者:


但是该机器人很高兴地收到VideoNote轮回消息,甚至以相同的轮回形式答复它们:


看起来视频和声音是相同的,但这只是乍一看。如果我们的机器人给了我们一些秘密信号怎么办?为了找出答案,我们将保存原始视频并将其与漫游器的响应进行比较。对于此步骤和后续步骤,FFmpeg软件包对我们来说非常有用那么,让我们看看那里是什么:



格式为aac-> flac,频率为44100 Hz-> 98000 Hz。我们发现,继续与音频一起工作。

通过灵巧的动作,我们将其从视频中拉出:


我们的原始消息也可以这样做,以便稍后进行比较。为了清楚起见,请在Audacity中打开两个轨道


机器人的音频响应中幅度的跳跃立即引起您的注意(如果我们完全保持沉默,则尤其奇怪)。在仔细检查时,我们注意到间隔“ wave-silence”期间的清晰边界:


我们建议将所有内容放在一旁,再数一点。我们按片段进行分析:

0-0.005-静默
0.005-0.01-波
0,01-0.0225-静默
0.025-0.04-波
0.04-0.045-静默

最小间隔为0.005,其他所有间隔间隔是0.005的倍数。
对于1,出现0.005的波动,对于0,则保持沉默。除了二进制代码,我们什么都没有!
我们记得频率已经改变,请尝试查看频谱图(分析->频谱图):


我们看到最强大的信号是〜44100 Hz的频率,即超声波。
因此,那么您应该只在高频下工作。

实际上,机器人将其信号叠加到可听频谱中的原始音频上。在原始视频中有声音的那些参与者在Audacity中注意到了这一点。

我们在Audacity或同一ffmpeg中使用高通滤波器来切断高频:


因此,我们有一个16位的单声道wav文件。它由标题,未压缩的音频流和元数据组成。音频流本身分为帧(帧可以存储几个样本,但这是一个完全不同的故事),在我们的示例中,每个16位(在屏幕快照中由字母pcm_s16表示)。帧是描述一个或多个通道(在我们的情况下是一个通道)一次的波幅的比特序列。音频流的采样频率为98000帧(即每秒98000帧),每0.005秒间隔490帧。

因此,我们进一步根据一种简单的算法进行工作:读取490帧,确定是波浪还是静默,并根据此位将其设置为0或1。我们将

使用python和一个包wave用于解析wav文件。
如果打开文件时发生错误“ wave.Error:未知格式:65534”,则将标题中的“ wFormatTag”从“ FE FF”替换为“ 01 00”:

fh = open(input_file, "r+b")
fh.seek(20)
fh.write(b'\x01\x00')
fh.close()

因此,打开文件,处理490帧并计算平均值:

file = wave.open(input_file,"r")
    for i in range (1, int(file.getnframes()/490)+1):
        frames = file.readframes(490)
        bit = 0
        sum = 0
        for k in range(0, 246):
            frame_bytes = frames[k*2:k*2+2]
            sum += int.from_bytes(frame_bytes, "big")
        if sum/490 > 16000:
            bit = 1
        bits.append(bit)

可能应该保持安静的地方(与Audacity中的图像比较),可能会残留噪音。因此,我们设置阈值(设为16000),超过该阈值,我们认为信号为1。

然后将这些位分组为字节:

bytes = []    
for i in range (1, int(len(bits)/8)+1):
        b1 = bits[i*8-8]
        b2 = bits[i*8-7]
        b3 = bits[i*8-6]
        b4 = bits[i*8-5]
        b5 = bits[i*8-4]
        b6 = bits[i*8-3]
        b7 = bits[i*8-2]
        b8 = bits[i*8-1]
        byte = (b1 << 7) | (b2 << 6) | (b3 << 5) | (b4 << 4) | (b5 << 3) | (b6 << 2) | (b7 << 1) | b8
        bytes.append(byte.to_bytes(1, byteorder='big')) 

如果一切正确,则结果为字符串“ Givemethepassword”。由于该漫游器使用隐写术在圈子中进行通信,因此以相同的格式为它设置密码(由于解密,我们将其与密钥一起接收)是合乎逻辑的。

首先,用密码撰写音轨。为此,我们使用在分析来自机器人的消息期间获得的数据:采样频率98000 Hz;采样频率98000 Hz。描述每个比特的信号的持续时间为5 ms;从图中可以看到,对应于比特值“ 1”的信号频率为44100 Hz。

现在我们需要“产生”沉默。我们通过中和来做到这一点:

sample_rate = 98000.0
def generate_silence(duration_milliseconds=5):
    fragment = []
    num_samples = duration_milliseconds * (sample_rate / 1000.0)
    for x in range(int(num_samples)): 
        fragment.append(0.0)
    return fragment

为了产生声音,我们将使用正弦波(可在此处阅读信息):

def generate_sinewave(
        freq=41000.0, 
        duration_milliseconds=5, 
        volume=0.5):
    fragment = []
    amplitude = volume * 32767.0
    num_samples = duration_milliseconds * (sample_rate / 1000.0)
    for x in range(int(num_samples)):
        fragment.append(amplitude * math.sin(2 * math.pi * freq * ( x / sample_rate )))
    return fragment

现在事情很小了:仍然需要将密码转换为位,然后转换为声音。

注意:如前所述,机器人使用原始输入视频轨道覆盖其消息。因此,您需要在密码后添加一些零字节,以便从机器人中删除整个密钥,而不仅仅是其开头(密钥长度为36个字节)。

声音产生
    audio = []
    f = open(input_file, 'rb')
    for character in f.read():
        a = character
        b8 = a & 0b00000001 
        b7 = (a & 0b00000010) >> 1 
        b6 = (a & 0b00000100) >> 2
        b5 = (a & 0b00001000) >> 3
        b4 = (a & 0b00010000) >> 4
        b3 = (a & 0b00100000) >> 5
        b2 = (a & 0b01000000) >> 6
        b1 = (a & 0b10000000) >> 7
        if b1 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b2 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b3 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b4 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b5 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b6 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b7 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()
        if b8 == 1:
            audio += generate_sinewave()
        else:
            audio += generate_silence()


现在,我们将创建完成的wave文件:

wav_file=wave.open(file_name,"w")
    nchannels = 1
    sampwidth = 2
    nframes = len(audio)
    comptype = "NONE"
    compname = "not compressed"
    wav_file.setparams((nchannels, sampwidth, sample_rate, nframes, comptype, compname))
    for sample in audio:
        wav_file.writeframes(struct.pack('h', int(sample)))
    wav_file.close()

我们将曲目保存在例如pass.wav中。在此过程中,我们使用隐身解码器检查密码是否被识别。如果一切顺利,那么我们将从原始视频my_video.mp4中获取一个带有密码的新视频,以替换音轨:


现在,我们需要用它来制作VideoNote。您可以尝试寻找工作对象(例如,一些参与者,例如@TelescopyBot),也可以使用TelegramAPI编写机器人。


无论如何,请转发给我们的机器人:


我们得到了新的一轮热烈的祝贺(我们会做这样的工作!),根据已经解决的情况对音频进行解码,然后得到密钥:“ nq2020SyOMK7SnnJP1sNlvbTs8zt35vUrrsD”

确实,隐秘技术无缘无故被认为是网络安全中最困难的领域之一-尝试在这里猜测所有这些!但是NeoQUEST参与者在执行此任务时表现出了出色的敏捷性和幽默感,因此我们正在表达诚挚的敬意(来自机器人的祝贺)!

All Articles