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.
- File #1: actf2020-4ea.txt
- File #2: actf2020-Noisey.py
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}