Noisy [misc]

Noisy

My furrier friend tried to send me a morse code message about some new furs, but he was using a noisy connection. I think he repeated it a few times but I still can't tell what he said, could you figure out what he was trying to tell me? Here's the code he used.

The flag is not in the actf{} format, it's all lowercase, 1 repetition only.

Recon

The actf2020-4ea.txt file contains 28800 different values and as mentioned in the description and as seen in the code: the message is repeated multiple times.

We can therefore bruteforce all divisors of 28800 where for each divisor we fold the values together and average them. This should partly eliminate the Gaussian noise.

We can then use a threshold to try and parse the values to morse and then to letters. One of the divisors should yield a readable result.

Code

morse = {
    '.-': 'a',
    '-...': 'b',
    '-.-.': 'c',
    '-..': 'd',
    '.': 'e',
    '..-.': 'f',
    '--.': 'g',
    '....': 'h',
    '..': 'i',
    '.---': 'j',
    '-.-': 'k',
    '.-..': 'l',
    '--': 'm',
    '-.': 'n',
    '---': 'o',
    '.--.': 'p',
    '--.-': 'q',
    '.-.': 'r',
    '...': 's',
    '-': 't',
    '..-': 'u',
    '...-': 'v',
    '.--': 'w',
    '-..-': 'x',
    '-.--': 'y',
    '--..': 'z',
    '/': ' ',
    '.----': '1',
    '..---': '2',
    '...--': '3',
    '....-': '4',
    '.....': '5',
    '-....': '6',
    '--...': '7',
    '---..': '8',
    '----.': '9',
    '-----': '0',
    '.-.-.-': '.',
    '--..--': ',',
    '..--..': '?',
    '---...': ':',
    '-....-': '-',
    '-.-.-.': ';',
    '-..-.': '/',
    '..--.-': '_',
    '-.--.': '(',
    '-.--.-': ')',
    '.-.-.': '+',
    '-...-': '='
}

def parse_morse(msg):
    return ''.join([morse[token] for token in msg.split(' ') if token in morse])

with open('4ea.txt') as f:
    data = [float(x) for x in f.read().split('\n') if len(x) > 0]

divisors = [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 30, 32, 36, 40, 45, 48, 50, 60, 64, 72, 75, 80, 90, 96, 100, 120, 128, 144, 150, 160, 180, 192, 200, 225, 240, 288, 300, 320, 360, 384, 400, 450, 480, 576, 600, 640, 720, 800, 900, 960, 1152, 1200, 1440, 1600, 1800, 1920, 2400, 2880, 3200, 3600, 4800, 5760, 7200, 9600, 14400]
threshold = 0.25

for div in divisors:
    part = len(data) // div
    div_data = [x / div for x in data[:part]]
    for p in range(1, div):
        for i, q in enumerate(data[p * part:(p + 1) * part]):
            div_data[i] += (q / div)
    m = ''
    b = 0
    while b < len(div_data):
        p1 = sum(div_data[b:b+10]) / 10
        p2 = sum(div_data[b+10:b+20]) / 10
        p3 = sum(div_data[b:b+20]) / 20
        p4 = sum(div_data[b+20:b+30]) / 10
        if p1 >= threshold and p2 <= -threshold:
            m += '.'
            b += 20
        elif p3 >= threshold and p4 <= -threshold:
            m += '-'
            b += 30
        elif p3 <= -threshold and p4 <= -threshold:
            m += ' '
            b += 30
        else:
            break
    print(f'{div} {len(div_data)}: {parse_morse(m)}')

Flag

actf{anoisynoise}