Mommy morse

The little warm up with daddy morse is now over, let’s see what mommy has to offer !

What is this about ?

Daddy morse was just about transmitting on or off signals (well, kindof). Mommy morse wants us to fiddle with frequencies and all: I’m pretty sure that this whole thing is about Frequency modulation/Frequency shift keying. We have to encode data the following way:

  • sample rate: 24kHz
  • . : 5kHz carrier wave for 1ms
  • -: 5kHz carrier wave for 5ms
  • Space between two letters: 1kHz carrier wave for 5ms
  • Space between two words: 1kHz carrier wave for 20ms

To flag this challenge, I was at first trying to do everything in python with numpy, just as I did with Daddy morse. In the end, I just kept the message -> AM part and did the rest in Gnu Radio.

Message -> AM

Here is the script that I used to generate my AM signal:

import numpy as np

SAMP_RATE = 24e3
TIMING_DOT = 1/1000
TIMING_DASH = 5/1000
TIMING_SEP_LETTER = 5/1000
TIMING_SPACE = 20/1000

dot_count = int(TIMING_DOT * SAMP_RATE)
dash_count = int(TIMING_DASH * SAMP_RATE)
letters_count = int(TIMING_SEP_LETTER * SAMP_RATE)
word_count = int(TIMING_SPACE * SAMP_RATE)

alphabet = { '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 build(phrase):
    res = []
    for w in phrase.split(" "):
        tmp = ""
        for l in w:
            if l not in alphabet:
                pass
            else:
                tmp += "{} ".format(alphabet[l])
        res.append(tmp[:-1])

    return res

def generate(morse):
    res = []
    for w in morse:
        for c in w:
            if c == ".":
                data = [(1+1j) for _ in range(dot_count)] + [0j for _ in range(dot_count)]
            elif c == "-":
                data = [(1+1j) for _ in range(dash_count)] + [0j for _ in range(dot_count)]
            else:
                data = [0j for _ in range(letters_count)]
                res = res[:-dot_count]
            res.extend(data)

        if w[-1] == '.' or w[-1] == '-':
            res = res[:-dot_count]
        res.extend([0j] * word_count)

    res = res[:-word_count]
    return np.array(res,dtype=np.complex64)

sentence = "CAN I GET THE FLAG"
morse = build(sentence)
data = generate(morse)
filename = sentence.replace(" ", "-").lower()

print(f"Writing data to {filename}.iq")
with open(f"{filename}.iq", "wb") as file:
    file.write(data)

Quick launch:

1 ❯ python hardware/mommymorse/script.py 
Writing data to can-i-get-the-flag.iq
0

And let’s see if URH appreciates what I’ve done: img

It does !

AM -> FM

Now that is the fun part of the challenge! Here’s what I’ve done: img

You can open and try this circuit by yourself with script.grc.

Kesseussai ????

Okay sorry, please bear with me.

First and foremost, set the samp_rate variable to 24KHz as specified by the challenge, this is important.

Then, load the AM signal with a File Source block (do not forget to turn off repeat on this block or your FM file won’t work with this challenge).

Create a constant source block that always outputs (1 + 1j) and link both that block and the file source to a subtract block: this will give us the opposite of our AM signal.

Create two signal sources, one at 1KHz (for the spaces) and one at 5KHz (for the non-spaces chars), they will be used to convert that AM signal to FM. Now create two multiply blocks:

  • Link the subtract block and the 1KHz signal source with the first multiply
  • Link the File source and the 5KHz signal with the second multiply

This will transform this (AM): img

Into this (FM): img

We still need to add these two multiply blocks, so create add Add block and link them with it.

And that’s pretty much it, link your add block to a file sink (and some graphs if you like to visualize your hard work) and voila:

img

Lemme get the flag

Just a little edit to the client.py a bit:

from pwn import *
import numpy as np
import base64

HOST = args.HOST or "challenges.france-cybersecurity-challenge.fr"
PORT = args.PORT or  2252

c = remote(HOST, PORT)

hello_signal = np.fromfile("res.iq", dtype = np.complex64)

encoded_signal = base64.b64encode(hello_signal.tobytes())

c.recvuntil(b"> ")
c.sendline(encoded_signal)
print(c.recvline())

Now just go ahead and execute it:

0 hardware/mommy morse❯ python client.py
[+] Opening connection to challenges.france-cybersecurity-challenge.fr on port 2252: Done
b'Well done: FCSC{490b88345a22d35554b3e319b1200b985cc7683e975969d07841cd56dd488649}\n'
[*] Closed connection to challenges.france-cybersecurity-challenge.fr port 2252