--- date: 2022-04-30 toc: true title: Mommy morse tags: ["FCSC2022", "hardware"] --- 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: ```python 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: ```sh 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](https://notes.alxczl.fr/uploads/3d47d9b47a6ee23685015020e.png) It does ! ## AM -> FM Now that is the fun part of the challenge! Here's what I've done: ![img](https://notes.alxczl.fr/uploads/3d47d9b47a6ee23685015020f.png) 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](https://notes.alxczl.fr/uploads/3d47d9b47a6ee236850150210.png) Into this (FM): ![img](https://notes.alxczl.fr/uploads/3d47d9b47a6ee236850150211.png) 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](https://notes.alxczl.fr/uploads/3d47d9b47a6ee236850150212.png) # Lemme get the flag Just a little edit to the `client.py` a bit: ```python 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: ```sh 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 ```