Published on

# IrisCTF 2024 – Sharing is Caring

Authors

## Sharing is Caring (Networks, 1 Solve)

Sharing is caring, don’t ya know? Sharing a communications channel, that is!

Eve is trying to read Alice’s messages, but she doesn’t know how to make sense of any of the data being received over the network. This isn’t your typical home network either, but something else within the network and communications space.

Eve and Alice are the only people connected to the network in this area. They share the channel, and if anyone else joined the network, they would likewise have to share the channel. Alice has only 1 device and Eve controls the rest. Eve has the signal and of course her own keys, attached.

Can you recover Alice’s messages?

Hint - I wasn’t sure whether or not to put this in RF or networks, but decided on networks since the path to get to the solution is more on the theoretical side of the fence and applicable to more than just RF. Hopefully that should give you an idea of where to start!

Author: skat

This problem was categorized as "Networks", although a note from the author said it could also fit in the RF (Radio Frequency) category. I went into this not really knowing much at all about the topic, but used ChatGPT, googlefu, and lots of analysis to figure out the solution!

Let’s first analyze the prompt because it gave important context that was needed to solve the challenge. There are two people sharing a single communication channel, Eve and Alice. Alice has a single device connected to the channel, presumably sending out the flag. Eve has multiple devices, which I’m assuming are also transmitting information on the channel. It also states that this "isn’t your typical home network", which means the communications/networking setup here is uncommon.

Here’s the important thing to note about channels: one of their biggest enemies is collisions. If two people transmit at the same time on the same channel, then their signals will mix (amplitudes will add up) and it can make the signals indistinguishable. So since both Alice and Eve are transmitting on the same channel, we need to figure out how to isolate Alice’s signal from Eve’s signals to retrieve the flag.

### Red Herring #1

My first thought went to something I learned about in my university’s Digital Communications class, CSMA. CSMA stands for "carrier-sense multiple access", and has two modes: collision avoidance and collision detection. CSMA is pretty much a way for multiple devices using the same communications channel to avoid and detect transmission collisions, which seems like our exact problem! I started doing research but everything I learned was pretty much just:

• Listen for data already being transmitted. If there’s data, then wait. If there’s not, then transmit.
• If a collision is detected, then both parties transmitting will stop, wait a random interval, then start again.

While important in modern-day networks, it didn’t seem super helpful in our case.

### Analyzing the Given Files

This is the perfect time to discuss and analyze the files we were presented with. Inside the compressed archive were 5 files: 1.key, 2.key, 3.key, 4.key, and signal.txt. Each of the key files were filled with 200 random bytes, no strings or magic bytes or anything.

00000000: 94e7 b524 b466 10b1 2604 a6d3 29a5 6911  ...$.f..&...).i. 00000010: bf95 b7b3 5ae5 96a4 2a40 b939 4755 ba35 ....Z...*@.9GU.5 00000020: f17b d723 d7a2 1808 f26c 7dc4 d29f 1cb8 .{.#.....l}..... ...  That was the last pattern that I needed to find before I put all the puzzle pieces together. ### CDMA I was still struggling to figure out how it was possible to isolate a single signal from a collision mess of 5 signals when I asked ChatGPT. I knew it wasn’t TDMA or FDMA because these devices were transmitting with the same frequencies at the same time, but CDMA?? I had never heard of that! Apparently it uses "unique codes" (just like keys??) to differentiate their signals in some way. I went ahead and did more investigation into CDMA. I stumbled upon this website that described CDMA pretty well. A long, unique "code" (also known as a PN code, PRN code, or "key" in our situation) is used to send a message by multiplying it with a single bit from the message and sending that signal out. Remember how 1.key was encoded as the signal [-1, 1, 1, 1, -1, -1, 1, 1, ...]? Well, if the first bit from the message is a 1, then that signal is sent out. However, if the first bit is 0, then the opposite of that signal is sent out ([1, -1, -1, -1, 1, 1, -1, -1, ...]). The entire code/key is sent for a single bit of the message, which meant 1600 signal bits gave us 1 message bit. That’s a HUGELY inefficient ratio, but makes sense why 1.2 million signal bits were sent! That answers all the questions I posed except how to isolate the signals from one another, even if encoded in DS-CDMA. But some reasoning and Python helped me there! We have all 5 keys (or perhaps the opposite of Alice’s key, but that can easily be resolved with testing), and know only those 5 devices are transmitting. Each device will either transmit their key or the opposite of their key, so 2 possibilities. With 5 devices, 2**5 is 32, meaning there are only 32 possible combinations of signals sent out. If I mapped each of those 32 possibilities out and split my signal into 1600-bit chunks, I could figure out which bits were being sent for each device at the same time! I decided to use MD5 hashes of these 1600-bit variations to match to our 32 possibilities and wrote this cool, little, script using perfect programming technique: import math from hashlib import md5 ### SIGNAL DATA ### signal_data = eval(open('signal.txt','r').read()) # split signal_data into lists of 1600 data_segments = [signal_data[i:i+1600] for i in range(0, len(signal_data), 1600)] #print(data_segments) ### KEYS ### # keys in binary format (ie b'\x99\x34\x12') keys_b = [0, 0, 0, 0, 0] keys_b[0] = open('1.key','rb').read() keys_b[1] = open('2.key','rb').read() keys_b[2] = open('3.key','rb').read() keys_b[3] = open('4.key','rb').read() keys_b[4] = open('alice.key','rb').read() # keys in string format (ie ['1','0','1','0','1','0','1','0']) keys_s = [] for k in keys_b: keys_s.append([x for x in''.join([bin(x)[2:].zfill(8) for x in k])]) # keys in decoded format where 1 is -1 and 0 is 1 keys_d = [] for k in keys_s: tmp0 = [] tmp1 = [] for i in range(len(k)): if k[i] == '1': tmp0.append(-1) tmp1.append(1) else: tmp0.append(1) tmp1.append(-1) keys_d.append({'0':tmp0,'1':tmp1}) ### MESSAGE VARIATIONS ### def get_seq(key1, key2, key3, key4, key5): retval = [] for i in range(len(key1)): retval.append(key1[i] + key2[i] + key3[i] + key4[i] + key5[i]) hash = md5(''.join([str(x) for x in retval]).encode()).hexdigest() return hash variations = [] # i know this isn't good programming but idc variations.append(("00000",get_seq(keys_d[0]['0'],keys_d[1]['0'],keys_d[2]['0'],keys_d[3]['0'],keys_d[4]['0']))) variations.append(("00001",get_seq(keys_d[0]['0'],keys_d[1]['0'],keys_d[2]['0'],keys_d[3]['0'],keys_d[4]['1']))) variations.append(("00010",get_seq(keys_d[0]['0'],keys_d[1]['0'],keys_d[2]['0'],keys_d[3]['1'],keys_d[4]['0']))) variations.append(("00011",get_seq(keys_d[0]['0'],keys_d[1]['0'],keys_d[2]['0'],keys_d[3]['1'],keys_d[4]['1']))) variations.append(("00100",get_seq(keys_d[0]['0'],keys_d[1]['0'],keys_d[2]['1'],keys_d[3]['0'],keys_d[4]['0']))) # ... print(variations) ### LOOP THROUGH SEGMENTS ### for segment in data_segments: hash = md5(''.join([str(x) for x in segment]).encode()).hexdigest() for variation in variations: if hash == variation[1]: print(variation[0][-1],end='') break else: print("ERROR: hash not found")  Running the script: user@computer$ python3 solve.py
[('00000', '0d117435c56281b054522b58cdcb64fe'), ('00001', '2a1c1afc86d487558c615435f288bb7e'), ('00010', '17e8ae0b4c6135839883edb6474556ba'), ('00011', '13fb6b827c11f4e37a35a69f256a4b1d'), ('00100', '5b880d5f9efdb8110b06927b1970b8b2'), ('00101', '69556b97fb9ac2a162f4d5a633566bce'), ('00110', 'c831e945c9b78871d08af0639b606fc1'), ('00111', '7d8ffc868b8b2896f9a90f83a9f5cf93'), ('01000', '28a6e21c237ca53f13bba8e5829d7783'), ('01001', '24d84770cb6bb7d2359fc0b15e0f63f8'), ('01010', '989aaab62cac2639b1914ee5b7bff47e'), ('01011', '42246aaecd145b87855ac6d7f3e145ba'), ('01100', '128ab2324bacb26de1f55cec5f3a83f0'), ('01101', '2d629a5610238046d868fd5283d86db5'), ('01110', '9534dd64a74bfe14b88d70cb37d70824'), ('01111', 'ff353f0ef94c906d138174c382497354'), ('10000', '3ff55e64c1dd2f2f3f5d93d3595780a2'), ('10001', '5654bfafc4a3631e53454d38b96c7cc8'), ('10010', '636e5c3c098dd7391f6f18011ba2fd05'), ('10011', '0de67b7b65a73a7e54abc3c0c24f96a3'), ('10100', 'ae61d3ceb508ba6ead8a3f9489aba9e4'), ('10101', 'a608fdc445bed490ed983db2ffbe1db5'), ('10110', 'df11e52e16429ee547a0cca1b14b5f09'), ('10111', 'ec4a69e1554b9eef0a9e2b238bb2a588'), ('11000', 'e211579051e5df5a8c69d5631bb9982d'), ('11001', '57a1784ca874a96712d6c48633cc214d'), ('11010', '3eb893ec606ae2cd53e93565d1847708'), ('11011', '66701f5634aa2863343afdc0b2fa1ad2'), ('11100', '619dca459b3e9cf8e88392cfd393cc4c'), ('11101', 'e2e86a83556b27b8bdb1a0bc48260684'), ('11110', '5fda6619728927d9011400f7caf4e1f9'), ('11111', '969dbb210db5f3dfb2083788534c976d')]
01001000011001010111100100100000010000010110110001101001011000110110010100101100001000000110100001100101011100100110010100100111011100110010000001110100011010000110010100100000011001100110110001100001011001110011101000100000011010010111001001101001011100110110001101110100011001100111101100110000011010000101111101101110001100000101111101111001011011110111010101110110001100110101111101100100001100110110011001100101011000010111010000110011011001000101111101110011011100000111001000110011011000010110010001011111011100110011000101100111011011100110000101101100011100110101111101100001011011100110010001011111001100010110111001110100001100110111001001100011011001010111000001110100001100110110010001011111011011010111100101011111011000110011000001101101011011010111001101111101000000000000000000000000


Flag: irisctf{0h_n0_youv3_d3feat3d_spr3ad_s1gnals_and_1nt3rcept3d_my_c0mms}`